forked from loafle/openapi-generator-original
Merge branch 'develop_2.0' into develop_2.0_objc_contenttype
Conflicts: samples/client/petstore/objc/client/SWGPetApi.m
This commit is contained in:
commit
87a730b5a2
12
.gitignore
vendored
12
.gitignore
vendored
@ -22,7 +22,17 @@ samples/server-generator/scalatra/output
|
|||||||
samples/server-generator/node/output/node_modules
|
samples/server-generator/node/output/node_modules
|
||||||
samples/server-generator/scalatra/target
|
samples/server-generator/scalatra/target
|
||||||
samples/server-generator/scalatra/output/.history
|
samples/server-generator/scalatra/output/.history
|
||||||
|
samples/client/petstore/qt5cpp/PetStore/moc_*
|
||||||
|
samples/client/petstore/qt5cpp/PetStore/*.o
|
||||||
|
samples/client/petstore/objc/PetstoreClient.xcworkspace/xcuserdata
|
||||||
|
samples/client/petstore/qt5cpp/build-*
|
||||||
|
samples/client/petstore/qt5cpp/PetStore/PetStore
|
||||||
|
samples/client/petstore/qt5cpp/PetStore/Makefile
|
||||||
|
samples/client/petstore/java/hello.txt
|
||||||
|
samples/client/petstore/android-java/hello.txt
|
||||||
|
samples/client/petstore/objc/Build
|
||||||
|
samples/client/petstore/objc/Pods
|
||||||
|
samples/server/petstore/nodejs/node_modules
|
||||||
target
|
target
|
||||||
.idea
|
.idea
|
||||||
.lib
|
.lib
|
||||||
|
@ -150,8 +150,11 @@ JavaClientCodegen.java
|
|||||||
JaxRSServerCodegen.java
|
JaxRSServerCodegen.java
|
||||||
NodeJSServerCodegen.java
|
NodeJSServerCodegen.java
|
||||||
ObjcClientCodegen.java
|
ObjcClientCodegen.java
|
||||||
|
PerlClientCodegen.java
|
||||||
PhpClientCodegen.java
|
PhpClientCodegen.java
|
||||||
|
Python3ClientCodegen.java
|
||||||
PythonClientCodegen.java
|
PythonClientCodegen.java
|
||||||
|
Qt5CPPGenerator.java
|
||||||
RubyClientCodegen.java
|
RubyClientCodegen.java
|
||||||
ScalaClientCodegen.java
|
ScalaClientCodegen.java
|
||||||
ScalatraServerCodegen.java
|
ScalatraServerCodegen.java
|
||||||
|
@ -26,6 +26,6 @@ fi
|
|||||||
|
|
||||||
# if you've executed sbt assembly previously it will use that instead.
|
# 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"
|
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||||
ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l jaxrs -o samples/server/petstore/jaxrs"
|
ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l jaxrs -o samples/server/petstore/jaxrs -Dswagger.codegen.jaxrs.impl.source=src/main/java"
|
||||||
|
|
||||||
java $JAVA_OPTS -jar $executable $ags
|
java $JAVA_OPTS -jar $executable $ags
|
||||||
|
@ -54,10 +54,16 @@ public class Generate implements Runnable {
|
|||||||
"Pass in a URL-encoded string of name:header with a comma separating multiple values")
|
"Pass in a URL-encoded string of name:header with a comma separating multiple values")
|
||||||
private String auth;
|
private String auth;
|
||||||
|
|
||||||
|
@Option( name= {"-D"}, title = "system properties", description = "sets specified system properties in " +
|
||||||
|
"the format of name=value,name=value")
|
||||||
|
private String systemProperties;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
verbosed(verbose);
|
verbosed(verbose);
|
||||||
|
|
||||||
|
setSystemProperties();
|
||||||
|
|
||||||
ClientOptInput input = new ClientOptInput();
|
ClientOptInput input = new ClientOptInput();
|
||||||
|
|
||||||
if (isNotEmpty(auth)) {
|
if (isNotEmpty(auth)) {
|
||||||
@ -77,6 +83,17 @@ public class Generate implements Runnable {
|
|||||||
new DefaultGenerator().opts(input.opts(new ClientOpts()).swagger(swagger)).generate();
|
new DefaultGenerator().opts(input.opts(new ClientOpts()).swagger(swagger)).generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setSystemProperties() {
|
||||||
|
if( systemProperties != null && systemProperties.length() > 0 ){
|
||||||
|
for( String property : systemProperties.split(",")) {
|
||||||
|
int ix = property.indexOf('=');
|
||||||
|
if( ix > 0 && ix < property.length()-1 ){
|
||||||
|
System.setProperty( property.substring(0, ix), property.substring(ix+1) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true parameter, adds system properties which enables debug mode in generator
|
* If true parameter, adds system properties which enables debug mode in generator
|
||||||
* @param verbose - if true, enables debug mode
|
* @param verbose - if true, enables debug mode
|
||||||
|
@ -6,11 +6,9 @@
|
|||||||
<relativePath>../..</relativePath>
|
<relativePath>../..</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.wordnik</groupId>
|
|
||||||
<artifactId>swagger-codegen</artifactId>
|
<artifactId>swagger-codegen</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>swagger-codegen (core library)</name>
|
<name>swagger-codegen (core library)</name>
|
||||||
<version>2.1.1-M2-SNAPSHOT</version>
|
|
||||||
<build>
|
<build>
|
||||||
<sourceDirectory>src/main/java</sourceDirectory>
|
<sourceDirectory>src/main/java</sourceDirectory>
|
||||||
<defaultGoal>install</defaultGoal>
|
<defaultGoal>install</defaultGoal>
|
||||||
|
@ -56,4 +56,8 @@ public interface CodegenConfig {
|
|||||||
Map<String, Object> postProcessModels(Map<String, Object> objs);
|
Map<String, Object> postProcessModels(Map<String, Object> objs);
|
||||||
Map<String, Object> postProcessOperations(Map<String, Object> objs);
|
Map<String, Object> postProcessOperations(Map<String, Object> objs);
|
||||||
Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs);
|
Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs);
|
||||||
|
|
||||||
|
String apiFilename(String templateName, String tag);
|
||||||
|
|
||||||
|
boolean shouldOverwrite(String filename);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,6 @@ public class CodegenModel {
|
|||||||
public String defaultValue;
|
public String defaultValue;
|
||||||
public List<CodegenProperty> vars = new ArrayList<CodegenProperty>();
|
public List<CodegenProperty> vars = new ArrayList<CodegenProperty>();
|
||||||
public Set<String> imports = new HashSet<String>();
|
public Set<String> imports = new HashSet<String>();
|
||||||
public Boolean hasVars, emptyVars, hasMoreModels;
|
public Boolean hasVars, emptyVars, hasMoreModels, hasEnums;
|
||||||
public ExternalDocs externalDocs;
|
public ExternalDocs externalDocs;
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ package com.wordnik.swagger.codegen;
|
|||||||
public class CodegenParameter {
|
public class CodegenParameter {
|
||||||
public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam,
|
public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam,
|
||||||
isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer, secondaryParam;
|
isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer, secondaryParam;
|
||||||
public String baseName, paramName, dataType, collectionFormat, description, baseType;
|
public String baseName, paramName, dataType, collectionFormat, description, baseType, defaultValue;
|
||||||
public String jsonSchema;
|
public String jsonSchema;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,7 +34,8 @@ public class CodegenParameter {
|
|||||||
output.isBodyParam = this.isBodyParam;
|
output.isBodyParam = this.isBodyParam;
|
||||||
output.required = this.required;
|
output.required = this.required;
|
||||||
output.jsonSchema = this.jsonSchema;
|
output.jsonSchema = this.jsonSchema;
|
||||||
|
output.defaultValue = this.defaultValue;
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,10 @@ public class CodegenProperty {
|
|||||||
public String example;
|
public String example;
|
||||||
|
|
||||||
public String jsonSchema;
|
public String jsonSchema;
|
||||||
public Double minimum, maximum, exclusiveMinimum, exclusiveMaximum;
|
public Double minimum;
|
||||||
|
public Double maximum;
|
||||||
|
public Boolean exclusiveMinimum;
|
||||||
|
public Boolean exclusiveMaximum;
|
||||||
public Boolean hasMore = null, required = null, secondaryParam = null;
|
public Boolean hasMore = null, required = null, secondaryParam = null;
|
||||||
public Boolean isPrimitiveType, isContainer, isNotContainer;
|
public Boolean isPrimitiveType, isContainer, isNotContainer;
|
||||||
public boolean isEnum;
|
public boolean isEnum;
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
package com.wordnik.swagger.codegen;
|
package com.wordnik.swagger.codegen;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class CodegenResponse {
|
public class CodegenResponse {
|
||||||
public String code, message;
|
public String code, message;
|
||||||
public Boolean hasMore;
|
public Boolean hasMore;
|
||||||
public List<Map<String, String>> examples;
|
public List<Map<String, Object>> examples;
|
||||||
public final List<CodegenProperty> headers = new ArrayList<CodegenProperty>();
|
public final List<CodegenProperty> headers = new ArrayList<CodegenProperty>();
|
||||||
public String dataType, baseType, containerType;
|
public String dataType, baseType, containerType;
|
||||||
|
public Boolean isDefault;
|
||||||
public Boolean simpleType;
|
public Boolean simpleType;
|
||||||
public Boolean primitiveType;
|
public Boolean primitiveType;
|
||||||
public Boolean isMapContainer;
|
public Boolean isMapContainer;
|
||||||
public Boolean isListContainer;
|
public Boolean isListContainer;
|
||||||
public Object schema;
|
public Object schema;
|
||||||
public String jsonSchema;
|
public String jsonSchema;
|
||||||
}
|
public boolean isWildcard() { return "0".equals(code) || "default".equals(code); }
|
||||||
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package com.wordnik.swagger.codegen;
|
package com.wordnik.swagger.codegen;
|
||||||
|
|
||||||
public class CodegenSecurity {
|
public class CodegenSecurity {
|
||||||
String name;
|
public String name;
|
||||||
String type;
|
public String type;
|
||||||
Boolean hasMore, isBasic, isOAuth, isApiKey;
|
public Boolean hasMore, isBasic, isOAuth, isApiKey;
|
||||||
// ApiKey specific
|
// ApiKey specific
|
||||||
String keyParamName;
|
public String keyParamName;
|
||||||
Boolean isKeyInQuery, isKeyInHeader;
|
public Boolean isKeyInQuery, isKeyInHeader;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,58 @@
|
|||||||
package com.wordnik.swagger.codegen;
|
package com.wordnik.swagger.codegen;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.wordnik.swagger.codegen.examples.ExampleGenerator;
|
import com.wordnik.swagger.codegen.examples.ExampleGenerator;
|
||||||
import com.wordnik.swagger.models.*;
|
import com.wordnik.swagger.models.ArrayModel;
|
||||||
|
import com.wordnik.swagger.models.Model;
|
||||||
|
import com.wordnik.swagger.models.ModelImpl;
|
||||||
|
import com.wordnik.swagger.models.Operation;
|
||||||
|
import com.wordnik.swagger.models.RefModel;
|
||||||
|
import com.wordnik.swagger.models.Response;
|
||||||
|
import com.wordnik.swagger.models.Swagger;
|
||||||
import com.wordnik.swagger.models.auth.ApiKeyAuthDefinition;
|
import com.wordnik.swagger.models.auth.ApiKeyAuthDefinition;
|
||||||
import com.wordnik.swagger.models.auth.BasicAuthDefinition;
|
import com.wordnik.swagger.models.auth.BasicAuthDefinition;
|
||||||
import com.wordnik.swagger.models.auth.In;
|
import com.wordnik.swagger.models.auth.In;
|
||||||
import com.wordnik.swagger.models.auth.SecuritySchemeDefinition;
|
import com.wordnik.swagger.models.auth.SecuritySchemeDefinition;
|
||||||
import com.wordnik.swagger.models.parameters.*;
|
import com.wordnik.swagger.models.parameters.BodyParameter;
|
||||||
import com.wordnik.swagger.models.properties.*;
|
import com.wordnik.swagger.models.parameters.CookieParameter;
|
||||||
|
import com.wordnik.swagger.models.parameters.FormParameter;
|
||||||
|
import com.wordnik.swagger.models.parameters.HeaderParameter;
|
||||||
|
import com.wordnik.swagger.models.parameters.Parameter;
|
||||||
|
import com.wordnik.swagger.models.parameters.PathParameter;
|
||||||
|
import com.wordnik.swagger.models.parameters.QueryParameter;
|
||||||
|
import com.wordnik.swagger.models.parameters.SerializableParameter;
|
||||||
|
import com.wordnik.swagger.models.properties.AbstractNumericProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.ArrayProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.BooleanProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.DateProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.DateTimeProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.DecimalProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.DoubleProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.FloatProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.IntegerProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.LongProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.MapProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.Property;
|
||||||
|
import com.wordnik.swagger.models.properties.PropertyBuilder;
|
||||||
|
import com.wordnik.swagger.models.properties.RefProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.StringProperty;
|
||||||
import com.wordnik.swagger.util.Json;
|
import com.wordnik.swagger.util.Json;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class DefaultCodegen {
|
public class DefaultCodegen {
|
||||||
Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
|
Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
|
||||||
|
|
||||||
@ -166,6 +198,9 @@ public class DefaultCodegen {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toEnumName(CodegenProperty property) {
|
||||||
|
return StringUtils.capitalize(property.name) + "Enum";
|
||||||
|
}
|
||||||
|
|
||||||
public String escapeReservedWord(String name) {
|
public String escapeReservedWord(String name) {
|
||||||
throw new RuntimeException("reserved word " + name + " not allowed");
|
throw new RuntimeException("reserved word " + name + " not allowed");
|
||||||
@ -470,6 +505,7 @@ public class DefaultCodegen {
|
|||||||
}
|
}
|
||||||
if(impl.getProperties() != null && impl.getProperties().size() > 0) {
|
if(impl.getProperties() != null && impl.getProperties().size() > 0) {
|
||||||
m.hasVars = true;
|
m.hasVars = true;
|
||||||
|
m.hasEnums = false;
|
||||||
for(String key: impl.getProperties().keySet()) {
|
for(String key: impl.getProperties().keySet()) {
|
||||||
Property prop = impl.getProperties().get(key);
|
Property prop = impl.getProperties().get(key);
|
||||||
|
|
||||||
@ -497,6 +533,8 @@ public class DefaultCodegen {
|
|||||||
}
|
}
|
||||||
m.vars.add(cp);
|
m.vars.add(cp);
|
||||||
count += 1;
|
count += 1;
|
||||||
|
if (cp.isEnum)
|
||||||
|
m.hasEnums = true;
|
||||||
if(count != impl.getProperties().keySet().size())
|
if(count != impl.getProperties().keySet().size())
|
||||||
cp.hasMore = new Boolean(true);
|
cp.hasMore = new Boolean(true);
|
||||||
if(cp.isContainer != null) {
|
if(cp.isContainer != null) {
|
||||||
@ -589,7 +627,7 @@ public class DefaultCodegen {
|
|||||||
|
|
||||||
// this can cause issues for clients which don't support enums
|
// this can cause issues for clients which don't support enums
|
||||||
if(property.isEnum)
|
if(property.isEnum)
|
||||||
property.datatypeWithEnum = StringUtils.capitalize(property.name) + "Enum";
|
property.datatypeWithEnum = toEnumName(property);
|
||||||
else
|
else
|
||||||
property.datatypeWithEnum = property.datatype;
|
property.datatypeWithEnum = property.datatype;
|
||||||
|
|
||||||
@ -692,11 +730,11 @@ public class DefaultCodegen {
|
|||||||
for(String key: operation.getConsumes()) {
|
for(String key: operation.getConsumes()) {
|
||||||
Map<String, String> mediaType = new HashMap<String, String>();
|
Map<String, String> mediaType = new HashMap<String, String>();
|
||||||
mediaType.put("mediaType", key);
|
mediaType.put("mediaType", key);
|
||||||
|
count += 1;
|
||||||
if (count < operation.getConsumes().size())
|
if (count < operation.getConsumes().size())
|
||||||
mediaType.put("hasMore", "true");
|
mediaType.put("hasMore", "true");
|
||||||
else
|
else
|
||||||
mediaType.put("hasMore", null);
|
mediaType.put("hasMore", null);
|
||||||
count += 1;
|
|
||||||
c.add(mediaType);
|
c.add(mediaType);
|
||||||
}
|
}
|
||||||
op.consumes = c;
|
op.consumes = c;
|
||||||
@ -722,7 +760,6 @@ public class DefaultCodegen {
|
|||||||
|
|
||||||
if (operation.getResponses() != null && !operation.getResponses().isEmpty()) {
|
if (operation.getResponses() != null && !operation.getResponses().isEmpty()) {
|
||||||
Response methodResponse = findMethodResponse(operation.getResponses());
|
Response methodResponse = findMethodResponse(operation.getResponses());
|
||||||
CodegenResponse methodCodegenResponse = null;
|
|
||||||
|
|
||||||
for (Map.Entry<String, Response> entry : operation.getResponses().entrySet()) {
|
for (Map.Entry<String, Response> entry : operation.getResponses().entrySet()) {
|
||||||
Response response = entry.getValue();
|
Response response = entry.getValue();
|
||||||
@ -732,9 +769,7 @@ public class DefaultCodegen {
|
|||||||
!defaultIncludes.contains(r.baseType) &&
|
!defaultIncludes.contains(r.baseType) &&
|
||||||
!languageSpecificPrimitives.contains(r.baseType))
|
!languageSpecificPrimitives.contains(r.baseType))
|
||||||
imports.add(r.baseType);
|
imports.add(r.baseType);
|
||||||
|
r.isDefault = response == methodResponse;
|
||||||
if (response == methodResponse)
|
|
||||||
methodCodegenResponse = r;
|
|
||||||
op.responses.add(r);
|
op.responses.add(r);
|
||||||
}
|
}
|
||||||
op.responses.get(op.responses.size() - 1).hasMore = false;
|
op.responses.get(op.responses.size() - 1).hasMore = false;
|
||||||
@ -904,6 +939,15 @@ public class DefaultCodegen {
|
|||||||
p.required = param.getRequired();
|
p.required = param.getRequired();
|
||||||
p.jsonSchema = Json.pretty(param);
|
p.jsonSchema = Json.pretty(param);
|
||||||
|
|
||||||
|
// move the defaultValue for headers, forms and params
|
||||||
|
if(param instanceof QueryParameter) {
|
||||||
|
p.defaultValue = ((QueryParameter)param).getDefaultValue();
|
||||||
|
} else if(param instanceof HeaderParameter) {
|
||||||
|
p.defaultValue = ((HeaderParameter)param).getDefaultValue();
|
||||||
|
} else if(param instanceof FormParameter) {
|
||||||
|
p.defaultValue = ((FormParameter)param).getDefaultValue();
|
||||||
|
}
|
||||||
|
|
||||||
if(param instanceof SerializableParameter) {
|
if(param instanceof SerializableParameter) {
|
||||||
SerializableParameter qp = (SerializableParameter) param;
|
SerializableParameter qp = (SerializableParameter) param;
|
||||||
Property property = null;
|
Property property = null;
|
||||||
@ -918,6 +962,19 @@ public class DefaultCodegen {
|
|||||||
collectionFormat = qp.getCollectionFormat();
|
collectionFormat = qp.getCollectionFormat();
|
||||||
CodegenProperty pr = fromProperty("inner", inner);
|
CodegenProperty pr = fromProperty("inner", inner);
|
||||||
p.baseType = pr.datatype;
|
p.baseType = pr.datatype;
|
||||||
|
p.isContainer = true;
|
||||||
|
imports.add(pr.baseType);
|
||||||
|
}
|
||||||
|
else if("object".equals(qp.getType())) {
|
||||||
|
Property inner = qp.getItems();
|
||||||
|
if(inner == null) {
|
||||||
|
LOGGER.warn("warning! No inner type supplied for map parameter \"" + qp.getName() + "\", using String");
|
||||||
|
inner = new StringProperty().description("//TODO automatically added by swagger-codegen");
|
||||||
|
}
|
||||||
|
property = new MapProperty(inner);
|
||||||
|
collectionFormat = qp.getCollectionFormat();
|
||||||
|
CodegenProperty pr = fromProperty("inner", inner);
|
||||||
|
p.baseType = pr.datatype;
|
||||||
imports.add(pr.baseType);
|
imports.add(pr.baseType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -926,6 +983,7 @@ public class DefaultCodegen {
|
|||||||
LOGGER.warn("warning! Property type \"" + qp.getType() + "\" not found for parameter \"" + param.getName() + "\", using String");
|
LOGGER.warn("warning! Property type \"" + qp.getType() + "\" not found for parameter \"" + param.getName() + "\", using String");
|
||||||
property = new StringProperty().description("//TODO automatically added by swagger-codegen. Type was " + qp.getType() + " but not supported");
|
property = new StringProperty().description("//TODO automatically added by swagger-codegen. Type was " + qp.getType() + " but not supported");
|
||||||
}
|
}
|
||||||
|
property.setRequired(param.getRequired());
|
||||||
CodegenProperty model = fromProperty(qp.getName(), property);
|
CodegenProperty model = fromProperty(qp.getName(), property);
|
||||||
p.collectionFormat = collectionFormat;
|
p.collectionFormat = collectionFormat;
|
||||||
p.dataType = model.datatype;
|
p.dataType = model.datatype;
|
||||||
@ -949,6 +1007,7 @@ public class DefaultCodegen {
|
|||||||
else {
|
else {
|
||||||
// TODO: missing format, so this will not always work
|
// TODO: missing format, so this will not always work
|
||||||
Property prop = PropertyBuilder.build(impl.getType(), null, null);
|
Property prop = PropertyBuilder.build(impl.getType(), null, null);
|
||||||
|
prop.setRequired(bp.getRequired());
|
||||||
CodegenProperty cp = fromProperty("property", prop);
|
CodegenProperty cp = fromProperty("property", prop);
|
||||||
if(cp != null) {
|
if(cp != null) {
|
||||||
p.dataType = cp.datatype;
|
p.dataType = cp.datatype;
|
||||||
@ -962,6 +1021,7 @@ public class DefaultCodegen {
|
|||||||
CodegenModel cm = fromModel(bp.getName(), impl);
|
CodegenModel cm = fromModel(bp.getName(), impl);
|
||||||
// get the single property
|
// get the single property
|
||||||
ArrayProperty ap = new ArrayProperty().items(impl.getItems());
|
ArrayProperty ap = new ArrayProperty().items(impl.getItems());
|
||||||
|
ap.setRequired(param.getRequired());
|
||||||
CodegenProperty cp = fromProperty("inner", ap);
|
CodegenProperty cp = fromProperty("inner", ap);
|
||||||
if(cp.complexType != null) {
|
if(cp.complexType != null) {
|
||||||
imports.add(cp.complexType);
|
imports.add(cp.complexType);
|
||||||
@ -996,9 +1056,9 @@ public class DefaultCodegen {
|
|||||||
if(schemes == null)
|
if(schemes == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
List<CodegenSecurity> secs = new ArrayList<CodegenSecurity>();
|
List<CodegenSecurity> secs = new ArrayList<CodegenSecurity>(schemes.size());
|
||||||
for(Iterator entries = schemes.entrySet().iterator(); entries.hasNext(); ) {
|
for (Iterator<Map.Entry<String, SecuritySchemeDefinition>> it = schemes.entrySet().iterator(); it.hasNext();) {
|
||||||
Map.Entry<String, SecuritySchemeDefinition> entry = (Map.Entry<String, SecuritySchemeDefinition>) entries.next();
|
final Map.Entry<String, SecuritySchemeDefinition> entry = it.next();
|
||||||
final SecuritySchemeDefinition schemeDefinition = entry.getValue();
|
final SecuritySchemeDefinition schemeDefinition = entry.getValue();
|
||||||
|
|
||||||
CodegenSecurity sec = CodegenModelFactory.newInstance(CodegenModelType.SECURITY);
|
CodegenSecurity sec = CodegenModelFactory.newInstance(CodegenModelType.SECURITY);
|
||||||
@ -1018,23 +1078,21 @@ public class DefaultCodegen {
|
|||||||
sec.isOAuth = !sec.isBasic;
|
sec.isOAuth = !sec.isBasic;
|
||||||
}
|
}
|
||||||
|
|
||||||
sec.hasMore = entries.hasNext();
|
sec.hasMore = it.hasNext();
|
||||||
secs.add(sec);
|
secs.add(sec);
|
||||||
}
|
}
|
||||||
return secs;
|
return secs;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Map<String, String>> toExamples(Map<String, String> examples) {
|
protected List<Map<String, Object>> toExamples(Map<String, Object> examples) {
|
||||||
if(examples == null)
|
if(examples == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
List<Map<String, String>> output = new ArrayList<Map<String, String>>();
|
final List<Map<String, Object>> output = new ArrayList<Map<String, Object>>(examples.size());
|
||||||
for(String key: examples.keySet()) {
|
for(Map.Entry<String, Object> entry : examples.entrySet()) {
|
||||||
String value = examples.get(key);
|
final Map<String, Object> kv = new HashMap<String, Object>();
|
||||||
|
kv.put("contentType", entry.getKey());
|
||||||
Map<String, String> kv = new HashMap<String, String>();
|
kv.put("example", entry.getValue());
|
||||||
kv.put("contentType", key);
|
|
||||||
kv.put("example", value);
|
|
||||||
output.add(kv);
|
output.add(kv);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
@ -1169,4 +1227,13 @@ public class DefaultCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String apiFilename(String templateName, String tag)
|
||||||
|
{
|
||||||
|
String suffix = apiTemplateFiles().get(templateName);
|
||||||
|
return apiFileFolder() + File.separator + toApiFilename(tag) + suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldOverwrite( String filename ){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,6 +165,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
|||||||
operation.putAll(config.additionalProperties());
|
operation.putAll(config.additionalProperties());
|
||||||
operation.put("classname", config.toApiName(tag));
|
operation.put("classname", config.toApiName(tag));
|
||||||
operation.put("classVarName", config.toApiVarName(tag));
|
operation.put("classVarName", config.toApiVarName(tag));
|
||||||
|
operation.put("importPath", config.toApiImport(tag));
|
||||||
|
|
||||||
|
processMimeTypes(swagger.getConsumes(), operation, "consumes");
|
||||||
|
processMimeTypes(swagger.getProduces(), operation, "produces");
|
||||||
|
|
||||||
allOperations.add(new HashMap<String, Object>(operation));
|
allOperations.add(new HashMap<String, Object>(operation));
|
||||||
for (int i = 0; i < allOperations.size(); i++) {
|
for (int i = 0; i < allOperations.size(); i++) {
|
||||||
@ -175,11 +179,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (String templateName : config.apiTemplateFiles().keySet()) {
|
for (String templateName : config.apiTemplateFiles().keySet()) {
|
||||||
String suffix = config.apiTemplateFiles().get(templateName);
|
|
||||||
String filename = config.apiFileFolder() +
|
String filename = config.apiFilename( templateName, tag );
|
||||||
File.separator +
|
if( new File( filename ).exists() && !config.shouldOverwrite( filename )){
|
||||||
config.toApiFilename(tag) +
|
continue;
|
||||||
suffix;
|
}
|
||||||
|
|
||||||
String template = readTemplate(config.templateDir() + File.separator + templateName);
|
String template = readTemplate(config.templateDir() + File.separator + templateName);
|
||||||
Template tmpl = Mustache.compiler()
|
Template tmpl = Mustache.compiler()
|
||||||
@ -217,6 +221,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
|||||||
bundle.put("models", allModels);
|
bundle.put("models", allModels);
|
||||||
bundle.put("apiFolder", config.apiPackage().replace('.', File.separatorChar));
|
bundle.put("apiFolder", config.apiPackage().replace('.', File.separatorChar));
|
||||||
bundle.put("modelPackage", config.modelPackage());
|
bundle.put("modelPackage", config.modelPackage());
|
||||||
|
bundle.put("authMethods", config.fromSecurity(swagger.getSecurityDefinitions()));
|
||||||
if (swagger.getExternalDocs() != null) {
|
if (swagger.getExternalDocs() != null) {
|
||||||
bundle.put("externalDocs", swagger.getExternalDocs());
|
bundle.put("externalDocs", swagger.getExternalDocs());
|
||||||
}
|
}
|
||||||
@ -291,6 +296,28 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processMimeTypes(List<String> mimeTypeList, Map<String, Object> operation, String source) {
|
||||||
|
if(mimeTypeList != null && mimeTypeList.size() > 0) {
|
||||||
|
List<Map<String, String>> c = new ArrayList<Map<String, String>>();
|
||||||
|
int count = 0;
|
||||||
|
for(String key: mimeTypeList) {
|
||||||
|
Map<String, String> mediaType = new HashMap<String, String>();
|
||||||
|
mediaType.put("mediaType", key);
|
||||||
|
count += 1;
|
||||||
|
if (count < mimeTypeList.size()) {
|
||||||
|
mediaType.put("hasMore", "true");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mediaType.put("hasMore", null);
|
||||||
|
}
|
||||||
|
c.add(mediaType);
|
||||||
|
}
|
||||||
|
operation.put(source, c);
|
||||||
|
String flagFieldName = "has" + source.substring(0, 1).toUpperCase() + source.substring(1);
|
||||||
|
operation.put(flagFieldName, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String, List<CodegenOperation>> processPaths(Map<String, Path> paths) {
|
public Map<String, List<CodegenOperation>> processPaths(Map<String, Path> paths) {
|
||||||
Map<String, List<CodegenOperation>> ops = new HashMap<String, List<CodegenOperation>>();
|
Map<String, List<CodegenOperation>> ops = new HashMap<String, List<CodegenOperation>>();
|
||||||
|
|
||||||
@ -427,6 +454,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
|||||||
CodegenModel cm = config.fromModel(key, mm);
|
CodegenModel cm = config.fromModel(key, mm);
|
||||||
Map<String, Object> mo = new HashMap<String, Object>();
|
Map<String, Object> mo = new HashMap<String, Object>();
|
||||||
mo.put("model", cm);
|
mo.put("model", cm);
|
||||||
|
mo.put("importPath", config.toModelImport(key));
|
||||||
models.add(mo);
|
models.add(mo);
|
||||||
allImports.addAll(cm.imports);
|
allImports.addAll(cm.imports);
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,33 @@
|
|||||||
package com.wordnik.swagger.codegen.examples;
|
package com.wordnik.swagger.codegen.examples;
|
||||||
|
|
||||||
import com.wordnik.swagger.models.*;
|
|
||||||
import com.wordnik.swagger.models.properties.*;
|
|
||||||
import com.wordnik.swagger.util.Json;
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
|
|
||||||
|
|
||||||
import javax.xml.bind.JAXBContext;
|
|
||||||
import javax.xml.bind.JAXBException;
|
|
||||||
import javax.xml.bind.Marshaller;
|
|
||||||
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.wordnik.swagger.models.Model;
|
||||||
|
import com.wordnik.swagger.models.ModelImpl;
|
||||||
|
import com.wordnik.swagger.models.properties.ArrayProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.BooleanProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.DateProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.DateTimeProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.DecimalProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.DoubleProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.FileProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.FloatProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.IntegerProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.LongProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.MapProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.ObjectProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.Property;
|
||||||
|
import com.wordnik.swagger.models.properties.RefProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.StringProperty;
|
||||||
|
import com.wordnik.swagger.models.properties.UUIDProperty;
|
||||||
|
import com.wordnik.swagger.util.Json;
|
||||||
|
|
||||||
public class ExampleGenerator {
|
public class ExampleGenerator {
|
||||||
protected Map<String, Model> examples;
|
protected Map<String, Model> examples;
|
||||||
@ -22,7 +36,7 @@ public class ExampleGenerator {
|
|||||||
this.examples = examples;
|
this.examples = examples;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Map<String, String>> generate(Map<String, String> examples, List<String> mediaTypes, Property property) {
|
public List<Map<String, String>> generate(Map<String, Object> examples, List<String> mediaTypes, Property property) {
|
||||||
List<Map<String, String>> output = new ArrayList<Map<String, String>>();
|
List<Map<String, String>> output = new ArrayList<Map<String, String>>();
|
||||||
Set<String> processedModels = new HashSet<String>();
|
Set<String> processedModels = new HashSet<String>();
|
||||||
if(examples == null ) {
|
if(examples == null ) {
|
||||||
@ -37,7 +51,6 @@ public class ExampleGenerator {
|
|||||||
String example = Json.pretty(resolvePropertyToExample(mediaType, property, processedModels));
|
String example = Json.pretty(resolvePropertyToExample(mediaType, property, processedModels));
|
||||||
|
|
||||||
if(example != null) {
|
if(example != null) {
|
||||||
example = example.replaceAll("\n", "\\\\n");
|
|
||||||
kv.put("example", example);
|
kv.put("example", example);
|
||||||
output.add(kv);
|
output.add(kv);
|
||||||
}
|
}
|
||||||
@ -45,7 +58,6 @@ public class ExampleGenerator {
|
|||||||
else if(property != null && mediaType.startsWith("application/xml")) {
|
else if(property != null && mediaType.startsWith("application/xml")) {
|
||||||
String example = new XmlExampleGenerator(this.examples).toXml(property);
|
String example = new XmlExampleGenerator(this.examples).toXml(property);
|
||||||
if(example != null) {
|
if(example != null) {
|
||||||
example = example.replaceAll("\n", "\\\\n");
|
|
||||||
kv.put("example", example);
|
kv.put("example", example);
|
||||||
output.add(kv);
|
output.add(kv);
|
||||||
}
|
}
|
||||||
@ -53,12 +65,10 @@ public class ExampleGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for(String key: examples.keySet()) {
|
for(Map.Entry<String, Object> entry: examples.entrySet()) {
|
||||||
String value = examples.get(key);
|
final Map<String, String> kv = new HashMap<String, String>();
|
||||||
|
kv.put("contentType", entry.getKey());
|
||||||
Map<String, String> kv = new HashMap<String, String>();
|
kv.put("example", Json.pretty(entry.getValue()));
|
||||||
kv.put("contentType", key);
|
|
||||||
kv.put("example", value);
|
|
||||||
output.add(kv);
|
output.add(kv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import com.wordnik.swagger.models.properties.*;
|
|||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.codehaus.plexus.util.StringUtils;
|
||||||
|
|
||||||
public class XmlExampleGenerator {
|
public class XmlExampleGenerator {
|
||||||
public static String NEWLINE = "\n";
|
public static String NEWLINE = "\n";
|
||||||
public static String TAG_START = "<";
|
public static String TAG_START = "<";
|
||||||
@ -16,6 +18,7 @@ public class XmlExampleGenerator {
|
|||||||
protected Map<String, Model> examples;
|
protected Map<String, Model> examples;
|
||||||
protected SimpleDateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
protected SimpleDateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
||||||
protected SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
protected SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
||||||
|
private static String EMPTY = "";
|
||||||
|
|
||||||
public XmlExampleGenerator(Map<String, Model> examples) {
|
public XmlExampleGenerator(Map<String, Model> examples) {
|
||||||
this.examples = examples;
|
this.examples = examples;
|
||||||
@ -24,29 +27,36 @@ public class XmlExampleGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toXml(Property property) {
|
public String toXml(Property property) {
|
||||||
return toXml(null, property, 0);
|
return toXml(null, property, 0, Collections.<String>emptySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String toXml(Model model, int indent) {
|
protected String toXml(Model model, int indent, Collection<String> path) {
|
||||||
if(model instanceof RefModel) {
|
if(model instanceof RefModel) {
|
||||||
RefModel ref = (RefModel) model;
|
RefModel ref = (RefModel) model;
|
||||||
Model actualModel = examples.get(ref.getSimpleRef());
|
Model actualModel = examples.get(ref.getSimpleRef());
|
||||||
if(actualModel instanceof ModelImpl)
|
if(actualModel instanceof ModelImpl)
|
||||||
return modelImplToXml((ModelImpl)actualModel, indent);
|
return modelImplToXml((ModelImpl) actualModel, indent, path);
|
||||||
}
|
}
|
||||||
else if(model instanceof ModelImpl) {
|
else if(model instanceof ModelImpl) {
|
||||||
return modelImplToXml((ModelImpl)model, indent);
|
return modelImplToXml((ModelImpl) model, indent, path);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String modelImplToXml(ModelImpl model, int indent) {
|
protected String modelImplToXml(ModelImpl model, int indent, Collection<String> path) {
|
||||||
|
final String modelName = model.getName();
|
||||||
|
if (path.contains(modelName)) {
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
final Set<String> selfPath = new HashSet<String>(path);
|
||||||
|
selfPath.add(modelName);
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
// attributes
|
// attributes
|
||||||
Map<String, Property> attributes = new LinkedHashMap<String, Property>();
|
Map<String, Property> attributes = new LinkedHashMap<String, Property>();
|
||||||
Map<String, Property> elements = new LinkedHashMap<String, Property>();
|
Map<String, Property> elements = new LinkedHashMap<String, Property>();
|
||||||
|
|
||||||
String name = model.getName();
|
String name = modelName;
|
||||||
String namespace;
|
String namespace;
|
||||||
String prefix;
|
String prefix;
|
||||||
Boolean wrapped;
|
Boolean wrapped;
|
||||||
@ -67,13 +77,17 @@ public class XmlExampleGenerator {
|
|||||||
sb.append(name);
|
sb.append(name);
|
||||||
for(String pName : attributes.keySet()) {
|
for(String pName : attributes.keySet()) {
|
||||||
Property p = attributes.get(pName);
|
Property p = attributes.get(pName);
|
||||||
sb.append(" ").append(pName).append("=").append(quote(toXml(null, p, 0)));
|
sb.append(" ").append(pName).append("=").append(quote(toXml(null, p, 0, selfPath)));
|
||||||
}
|
}
|
||||||
sb.append(CLOSE_TAG);
|
sb.append(CLOSE_TAG);
|
||||||
sb.append(NEWLINE);
|
sb.append(NEWLINE);
|
||||||
for(String pName : elements.keySet()) {
|
for(String pName : elements.keySet()) {
|
||||||
Property p = elements.get(pName);
|
Property p = elements.get(pName);
|
||||||
sb.append(toXml(pName, p, indent + 1));
|
final String asXml = toXml(pName, p, indent + 1, selfPath);
|
||||||
|
if (StringUtils.isEmpty(asXml)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sb.append(asXml);
|
||||||
sb.append(NEWLINE);
|
sb.append(NEWLINE);
|
||||||
}
|
}
|
||||||
sb.append(indent(indent)).append(TAG_END).append(name).append(CLOSE_TAG);
|
sb.append(indent(indent)).append(TAG_END).append(name).append(CLOSE_TAG);
|
||||||
@ -85,7 +99,7 @@ public class XmlExampleGenerator {
|
|||||||
return "\"" + string + "\"";
|
return "\"" + string + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String toXml(String name, Property property, int indent) {
|
protected String toXml(String name, Property property, int indent, Collection<String> path) {
|
||||||
if(property == null) {
|
if(property == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -98,12 +112,16 @@ public class XmlExampleGenerator {
|
|||||||
if(property.getXml() != null && property.getXml().getWrapped())
|
if(property.getXml() != null && property.getXml().getWrapped())
|
||||||
wrapped = true;
|
wrapped = true;
|
||||||
if(wrapped) {
|
if(wrapped) {
|
||||||
|
String prefix = EMPTY;
|
||||||
if(name != null) {
|
if(name != null) {
|
||||||
sb.append(indent(indent));
|
sb.append(indent(indent));
|
||||||
sb.append(openTag(name));
|
sb.append(openTag(name));
|
||||||
sb.append(NEWLINE);
|
prefix = NEWLINE;
|
||||||
|
}
|
||||||
|
final String asXml = toXml(name, inner, indent + 1, path);
|
||||||
|
if (StringUtils.isNotEmpty(asXml)) {
|
||||||
|
sb.append(prefix).append(asXml);
|
||||||
}
|
}
|
||||||
sb.append(toXml(name, inner, indent + 1));
|
|
||||||
if(name != null) {
|
if(name != null) {
|
||||||
sb.append(NEWLINE);
|
sb.append(NEWLINE);
|
||||||
sb.append(indent(indent));
|
sb.append(indent(indent));
|
||||||
@ -111,12 +129,12 @@ public class XmlExampleGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sb.append(toXml(name, inner, indent));
|
sb.append(toXml(name, inner, indent, path));
|
||||||
}
|
}
|
||||||
else if(property instanceof RefProperty) {
|
else if(property instanceof RefProperty) {
|
||||||
RefProperty ref = (RefProperty) property;
|
RefProperty ref = (RefProperty) property;
|
||||||
Model actualModel = examples.get(ref.getSimpleRef());
|
Model actualModel = examples.get(ref.getSimpleRef());
|
||||||
sb.append(toXml(actualModel, indent));
|
sb.append(toXml(actualModel, indent, path));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(name != null) {
|
if(name != null) {
|
||||||
|
@ -0,0 +1,365 @@
|
|||||||
|
package com.wordnik.swagger.codegen.languages;
|
||||||
|
|
||||||
|
import com.google.common.base.CaseFormat;
|
||||||
|
import com.samskivert.mustache.Mustache;
|
||||||
|
import com.samskivert.mustache.Template;
|
||||||
|
import com.wordnik.swagger.codegen.*;
|
||||||
|
import com.wordnik.swagger.models.auth.SecuritySchemeDefinition;
|
||||||
|
import com.wordnik.swagger.models.properties.*;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||||
|
Logger LOGGER = LoggerFactory.getLogger(AkkaScalaClientCodegen.class);
|
||||||
|
|
||||||
|
protected String mainPackage = "io.swagger.client";
|
||||||
|
|
||||||
|
protected String invokerPackage = mainPackage + ".core";
|
||||||
|
protected String groupId = "com.wordnik";
|
||||||
|
protected String artifactId = "swagger-client";
|
||||||
|
protected String artifactVersion = "1.0.0";
|
||||||
|
protected String sourceFolder = "src/main/scala";
|
||||||
|
protected String resourcesFolder = "src/main/resources";
|
||||||
|
protected String configKey = "apiRequest";
|
||||||
|
protected int defaultTimeoutInMs = 5000;
|
||||||
|
protected String configKeyPath = mainPackage;
|
||||||
|
|
||||||
|
protected boolean registerNonStandardStatusCodes = true;
|
||||||
|
protected boolean renderJavadoc = true;
|
||||||
|
protected boolean removeOAuthSecurities = true;
|
||||||
|
/**
|
||||||
|
* If set to true, only the default response (the one with le lowest 2XX code) will be considered as a success, and all
|
||||||
|
* others as ApiErrors.
|
||||||
|
* If set to false, all responses defined in the model will be considered as a success upon reception. Only http errors,
|
||||||
|
* unmarshalling problems and any other RuntimeException will be considered as ApiErrors.
|
||||||
|
*/
|
||||||
|
protected boolean onlyOneSuccess = true;
|
||||||
|
|
||||||
|
public CodegenType getTag() {
|
||||||
|
return CodegenType.CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return "akka-scala";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHelp() {
|
||||||
|
return "Generates a Scala client library base on Akka/Spray.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public AkkaScalaClientCodegen() {
|
||||||
|
super();
|
||||||
|
outputFolder = "generated-code/scala";
|
||||||
|
modelTemplateFiles.put("model.mustache", ".scala");
|
||||||
|
apiTemplateFiles.put("api.mustache", ".scala");
|
||||||
|
templateDir = "akka-scala";
|
||||||
|
apiPackage = mainPackage + ".api";
|
||||||
|
modelPackage = mainPackage + ".model";
|
||||||
|
|
||||||
|
reservedWords = new HashSet<String>(
|
||||||
|
Arrays.asList(
|
||||||
|
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
|
||||||
|
"false", "final", "finally", "for", "forSome", "if", "implicit",
|
||||||
|
"import", "lazy", "match", "new", "null", "object", "override", "package",
|
||||||
|
"private", "protected", "return", "sealed", "super", "this", "throw",
|
||||||
|
"trait", "try", "true", "type", "val", "var", "while", "with", "yield")
|
||||||
|
);
|
||||||
|
|
||||||
|
additionalProperties.put("invokerPackage", invokerPackage);
|
||||||
|
additionalProperties.put("groupId", groupId);
|
||||||
|
additionalProperties.put("artifactId", artifactId);
|
||||||
|
additionalProperties.put("artifactVersion", artifactVersion);
|
||||||
|
additionalProperties.put("configKey", configKey);
|
||||||
|
additionalProperties.put("configKeyPath", configKeyPath);
|
||||||
|
additionalProperties.put("defaultTimeout", defaultTimeoutInMs);
|
||||||
|
if (renderJavadoc)
|
||||||
|
additionalProperties.put("javadocRenderer", new JavadocLambda());
|
||||||
|
additionalProperties.put("fnCapitalize", new CapitalizeLambda());
|
||||||
|
additionalProperties.put("fnCamelize", new CamelizeLambda(false));
|
||||||
|
additionalProperties.put("fnEnumEntry", new EnumEntryLambda());
|
||||||
|
additionalProperties.put("onlyOneSuccess", onlyOneSuccess);
|
||||||
|
|
||||||
|
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
|
||||||
|
supportingFiles.add(new SupportingFile("reference.mustache", resourcesFolder, "reference.conf"));
|
||||||
|
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
|
||||||
|
supportingFiles.add(new SupportingFile("apiRequest.mustache", invokerFolder, "ApiRequest.scala"));
|
||||||
|
supportingFiles.add(new SupportingFile("apiInvoker.mustache", invokerFolder, "ApiInvoker.scala"));
|
||||||
|
supportingFiles.add(new SupportingFile("requests.mustache", invokerFolder, "requests.scala"));
|
||||||
|
supportingFiles.add(new SupportingFile("apiSettings.mustache", invokerFolder, "ApiSettings.scala"));
|
||||||
|
final String apiFolder = (sourceFolder + File.separator + apiPackage).replace(".", File.separator);
|
||||||
|
supportingFiles.add(new SupportingFile("enumsSerializers.mustache", apiFolder, "EnumsSerializers.scala"));
|
||||||
|
|
||||||
|
importMapping.remove("Seq");
|
||||||
|
importMapping.remove("List");
|
||||||
|
importMapping.remove("Set");
|
||||||
|
importMapping.remove("Map");
|
||||||
|
|
||||||
|
importMapping.put("DateTime", "org.joda.time.DateTime");
|
||||||
|
|
||||||
|
typeMapping = new HashMap<String, String>();
|
||||||
|
typeMapping.put("array", "Seq");
|
||||||
|
typeMapping.put("set", "Set");
|
||||||
|
typeMapping.put("boolean", "Boolean");
|
||||||
|
typeMapping.put("string", "String");
|
||||||
|
typeMapping.put("int", "Int");
|
||||||
|
typeMapping.put("integer", "Int");
|
||||||
|
typeMapping.put("long", "Long");
|
||||||
|
typeMapping.put("float", "Float");
|
||||||
|
typeMapping.put("byte", "Byte");
|
||||||
|
typeMapping.put("short", "Short");
|
||||||
|
typeMapping.put("char", "Char");
|
||||||
|
typeMapping.put("long", "Long");
|
||||||
|
typeMapping.put("double", "Double");
|
||||||
|
typeMapping.put("object", "Any");
|
||||||
|
typeMapping.put("file", "File");
|
||||||
|
typeMapping.put("number", "Double");
|
||||||
|
|
||||||
|
languageSpecificPrimitives = new HashSet<String>(
|
||||||
|
Arrays.asList(
|
||||||
|
"String",
|
||||||
|
"boolean",
|
||||||
|
"Boolean",
|
||||||
|
"Double",
|
||||||
|
"Int",
|
||||||
|
"Long",
|
||||||
|
"Float",
|
||||||
|
"Object",
|
||||||
|
"List",
|
||||||
|
"Seq",
|
||||||
|
"Map")
|
||||||
|
);
|
||||||
|
instantiationTypes.put("array", "ListBuffer");
|
||||||
|
instantiationTypes.put("map", "Map");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String escapeReservedWord(String name) {
|
||||||
|
return "`" + name + "`";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apiFileFolder() {
|
||||||
|
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String modelFileFolder() {
|
||||||
|
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||||
|
if (registerNonStandardStatusCodes) {
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, ArrayList<CodegenOperation>> opsMap = (Map<String, ArrayList<CodegenOperation>>) objs.get("operations");
|
||||||
|
HashSet<Integer> unknownCodes = new HashSet<Integer>();
|
||||||
|
for (CodegenOperation operation : opsMap.get("operation")) {
|
||||||
|
for (CodegenResponse response : operation.responses) {
|
||||||
|
if ("default".equals(response.code))
|
||||||
|
continue;
|
||||||
|
try {
|
||||||
|
int code = Integer.parseInt(response.code);
|
||||||
|
if (code >= 600) {
|
||||||
|
unknownCodes.add(code);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
LOGGER.error("Status code is not an integer : response.code", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!unknownCodes.isEmpty()) {
|
||||||
|
additionalProperties.put("unknownStatusCodes", unknownCodes);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Unable to find operations List", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.postProcessOperations(objs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CodegenSecurity> fromSecurity(Map<String, SecuritySchemeDefinition> schemes) {
|
||||||
|
final List<CodegenSecurity> codegenSecurities = super.fromSecurity(schemes);
|
||||||
|
if (!removeOAuthSecurities)
|
||||||
|
return codegenSecurities;
|
||||||
|
|
||||||
|
// Remove OAuth securities
|
||||||
|
Iterator<CodegenSecurity> it = codegenSecurities.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
final CodegenSecurity security = it.next();
|
||||||
|
if (security.isOAuth)
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
// Adapt 'hasMore'
|
||||||
|
it = codegenSecurities.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
final CodegenSecurity security = it.next();
|
||||||
|
security.hasMore = it.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codegenSecurities.isEmpty())
|
||||||
|
return null;
|
||||||
|
return codegenSecurities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toOperationId(String operationId) {
|
||||||
|
return super.toOperationId(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, operationId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatIdentifier(String name, boolean capitalized) {
|
||||||
|
String identifier = camelize(name, true);
|
||||||
|
if (capitalized)
|
||||||
|
identifier = StringUtils.capitalize(identifier);
|
||||||
|
if (identifier.matches("[a-zA-Z_$][\\w_$]+") && !reservedWords.contains(identifier))
|
||||||
|
return identifier;
|
||||||
|
return escapeReservedWord(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toParamName(String name) { return formatIdentifier(name, false); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toVarName(String name) {
|
||||||
|
return formatIdentifier(name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toEnumName(CodegenProperty property)
|
||||||
|
{
|
||||||
|
return formatIdentifier(property.baseName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSwaggerType(Property p) {
|
||||||
|
String swaggerType = super.getSwaggerType(p);
|
||||||
|
String type;
|
||||||
|
if (typeMapping.containsKey(swaggerType)) {
|
||||||
|
type = typeMapping.get(swaggerType);
|
||||||
|
if (languageSpecificPrimitives.contains(type))
|
||||||
|
return toModelName(type);
|
||||||
|
} else
|
||||||
|
type = swaggerType;
|
||||||
|
return toModelName(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toInstantiationType(Property p) {
|
||||||
|
if (p instanceof MapProperty) {
|
||||||
|
MapProperty ap = (MapProperty) p;
|
||||||
|
String inner = getSwaggerType(ap.getAdditionalProperties());
|
||||||
|
return instantiationTypes.get("map") + "[String, " + inner + "]";
|
||||||
|
} else if (p instanceof ArrayProperty) {
|
||||||
|
ArrayProperty ap = (ArrayProperty) p;
|
||||||
|
String inner = getSwaggerType(ap.getItems());
|
||||||
|
return instantiationTypes.get("array") + "[" + inner + "]";
|
||||||
|
} else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toDefaultValue(Property p) {
|
||||||
|
if (!p.getRequired())
|
||||||
|
return "None";
|
||||||
|
if (p instanceof StringProperty)
|
||||||
|
return "null";
|
||||||
|
else if (p instanceof BooleanProperty)
|
||||||
|
return "null";
|
||||||
|
else if (p instanceof DateProperty)
|
||||||
|
return "null";
|
||||||
|
else if (p instanceof DateTimeProperty)
|
||||||
|
return "null";
|
||||||
|
else if (p instanceof DoubleProperty)
|
||||||
|
return "null";
|
||||||
|
else if (p instanceof FloatProperty)
|
||||||
|
return "null";
|
||||||
|
else if (p instanceof IntegerProperty)
|
||||||
|
return "null";
|
||||||
|
else if (p instanceof LongProperty)
|
||||||
|
return "null";
|
||||||
|
else if (p instanceof MapProperty) {
|
||||||
|
MapProperty ap = (MapProperty) p;
|
||||||
|
String inner = getSwaggerType(ap.getAdditionalProperties());
|
||||||
|
return "Map[String, " + inner + "].empty ";
|
||||||
|
} else if (p instanceof ArrayProperty) {
|
||||||
|
ArrayProperty ap = (ArrayProperty) p;
|
||||||
|
String inner = getSwaggerType(ap.getItems());
|
||||||
|
return "Seq[" + inner + "].empty ";
|
||||||
|
} else
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static abstract class CustomLambda implements Mustache.Lambda {
|
||||||
|
@Override
|
||||||
|
public void execute(Template.Fragment frag, Writer out) throws IOException {
|
||||||
|
final StringWriter tempWriter = new StringWriter();
|
||||||
|
frag.execute(tempWriter);
|
||||||
|
out.write(formatFragment(tempWriter.toString()));
|
||||||
|
}
|
||||||
|
public abstract String formatFragment(String fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class JavadocLambda extends CustomLambda {
|
||||||
|
@Override
|
||||||
|
public String formatFragment(String fragment) {
|
||||||
|
final String[] lines = fragment.split("\\r?\\n");
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(" /**\n");
|
||||||
|
for (String line : lines) {
|
||||||
|
sb.append(" * ").append(line).append("\n");
|
||||||
|
}
|
||||||
|
sb.append(" */\n");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CapitalizeLambda extends CustomLambda {
|
||||||
|
@Override
|
||||||
|
public String formatFragment(String fragment) {
|
||||||
|
return StringUtils.capitalize(fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CamelizeLambda extends CustomLambda {
|
||||||
|
private final boolean capitalizeFirst;
|
||||||
|
|
||||||
|
public CamelizeLambda(boolean capitalizeFirst) {
|
||||||
|
this.capitalizeFirst = capitalizeFirst;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String formatFragment(String fragment) {
|
||||||
|
return camelize(fragment, !capitalizeFirst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class EnumEntryLambda extends CustomLambda {
|
||||||
|
@Override
|
||||||
|
public String formatFragment(String fragment) {
|
||||||
|
return formatIdentifier(fragment, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,6 +13,7 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
|
|||||||
protected String artifactVersion = "1.0.0";
|
protected String artifactVersion = "1.0.0";
|
||||||
protected String projectFolder = "src/main";
|
protected String projectFolder = "src/main";
|
||||||
protected String sourceFolder = projectFolder + "/java";
|
protected String sourceFolder = projectFolder + "/java";
|
||||||
|
protected Boolean useAndroidMavenGradlePlugin = true;
|
||||||
|
|
||||||
public CodegenType getTag() {
|
public CodegenType getTag() {
|
||||||
return CodegenType.CLIENT;
|
return CodegenType.CLIENT;
|
||||||
@ -52,6 +53,9 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
|
|||||||
additionalProperties.put("artifactVersion", artifactVersion);
|
additionalProperties.put("artifactVersion", artifactVersion);
|
||||||
|
|
||||||
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
|
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
|
||||||
|
additionalProperties.put("useAndroidMavenGradlePlugin", useAndroidMavenGradlePlugin);
|
||||||
|
|
||||||
|
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
|
||||||
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
|
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
|
||||||
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
|
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
|
||||||
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
|
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
|
||||||
|
@ -7,7 +7,7 @@ import java.util.*;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig {
|
public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||||
protected String invokerPackage = "io.swagger.client";
|
protected String invokerPackage = "IO.Swagger.Client";
|
||||||
protected String groupId = "io.swagger";
|
protected String groupId = "io.swagger";
|
||||||
protected String artifactId = "swagger-csharp-client";
|
protected String artifactId = "swagger-csharp-client";
|
||||||
protected String artifactVersion = "1.0.0";
|
protected String artifactVersion = "1.0.0";
|
||||||
@ -31,8 +31,8 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
modelTemplateFiles.put("model.mustache", ".cs");
|
modelTemplateFiles.put("model.mustache", ".cs");
|
||||||
apiTemplateFiles.put("api.mustache", ".cs");
|
apiTemplateFiles.put("api.mustache", ".cs");
|
||||||
templateDir = "csharp";
|
templateDir = "csharp";
|
||||||
apiPackage = "io.swagger.Api";
|
apiPackage = "IO.Swagger.Api";
|
||||||
modelPackage = "io.swagger.Model";
|
modelPackage = "IO.Swagger.Model";
|
||||||
|
|
||||||
reservedWords = new HashSet<String> (
|
reservedWords = new HashSet<String> (
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
@ -80,7 +80,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
typeMapping.put("double", "double?");
|
typeMapping.put("double", "double?");
|
||||||
typeMapping.put("number", "double?");
|
typeMapping.put("number", "double?");
|
||||||
typeMapping.put("Date", "DateTime");
|
typeMapping.put("Date", "DateTime");
|
||||||
typeMapping.put("file", "byte[]");
|
typeMapping.put("file", "string"); // path to file
|
||||||
typeMapping.put("array", "List");
|
typeMapping.put("array", "List");
|
||||||
typeMapping.put("map", "Dictionary");
|
typeMapping.put("map", "Dictionary");
|
||||||
|
|
||||||
|
@ -130,7 +130,6 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
return toModelName(name);
|
return toModelName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTypeDeclaration(Property p) {
|
public String getTypeDeclaration(Property p) {
|
||||||
if(p instanceof ArrayProperty) {
|
if(p instanceof ArrayProperty) {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.wordnik.swagger.codegen.languages;
|
package com.wordnik.swagger.codegen.languages;
|
||||||
|
|
||||||
import com.wordnik.swagger.models.Operation;
|
import com.wordnik.swagger.models.Operation;
|
||||||
import com.wordnik.swagger.models.Path;
|
|
||||||
import com.wordnik.swagger.util.Json;
|
|
||||||
import com.wordnik.swagger.codegen.*;
|
import com.wordnik.swagger.codegen.*;
|
||||||
import com.wordnik.swagger.models.properties.*;
|
import com.wordnik.swagger.models.properties.*;
|
||||||
|
|
||||||
@ -14,7 +12,6 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
|
|||||||
protected String groupId = "io.swagger";
|
protected String groupId = "io.swagger";
|
||||||
protected String artifactId = "swagger-jaxrs-server";
|
protected String artifactId = "swagger-jaxrs-server";
|
||||||
protected String artifactVersion = "1.0.0";
|
protected String artifactVersion = "1.0.0";
|
||||||
protected String sourceFolder = "src/main/java";
|
|
||||||
protected String title = "Swagger Server";
|
protected String title = "Swagger Server";
|
||||||
|
|
||||||
public CodegenType getTag() {
|
public CodegenType getTag() {
|
||||||
@ -31,12 +28,19 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
|
|||||||
|
|
||||||
public JaxRSServerCodegen() {
|
public JaxRSServerCodegen() {
|
||||||
super();
|
super();
|
||||||
outputFolder = "generated-code/javaJaxRS";
|
|
||||||
|
sourceFolder = "src/gen/java";
|
||||||
|
|
||||||
|
outputFolder = System.getProperty( "swagger.codegen.jaxrs.genfolder", "generated-code/javaJaxRS" );
|
||||||
modelTemplateFiles.put("model.mustache", ".java");
|
modelTemplateFiles.put("model.mustache", ".java");
|
||||||
apiTemplateFiles.put("api.mustache", ".java");
|
apiTemplateFiles.put("api.mustache", ".java");
|
||||||
|
apiTemplateFiles.put("apiService.mustache", ".java");
|
||||||
|
apiTemplateFiles.put("apiServiceImpl.mustache", ".java");
|
||||||
|
apiTemplateFiles.put("apiServiceFactory.mustache", ".java");
|
||||||
|
|
||||||
templateDir = "JavaJaxRS";
|
templateDir = "JavaJaxRS";
|
||||||
apiPackage = "io.swagger.api";
|
apiPackage = System.getProperty( "swagger.codegen.jaxrs.apipackage", "io.swagger.api") ;
|
||||||
modelPackage = "io.swagger.model";
|
modelPackage = System.getProperty( "swagger.codegen.jaxrs.modelpackage", "io.swagger.model" );
|
||||||
|
|
||||||
additionalProperties.put("invokerPackage", invokerPackage);
|
additionalProperties.put("invokerPackage", invokerPackage);
|
||||||
additionalProperties.put("groupId", groupId);
|
additionalProperties.put("groupId", groupId);
|
||||||
@ -146,4 +150,44 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
|
|||||||
}
|
}
|
||||||
return objs;
|
return objs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apiFilename(String templateName, String tag) {
|
||||||
|
|
||||||
|
String result = super.apiFilename(templateName, tag);
|
||||||
|
|
||||||
|
if( templateName.endsWith( "Impl.mustache")){
|
||||||
|
int ix = result.lastIndexOf( '/' );
|
||||||
|
result = result.substring( 0, ix ) + "/impl" + result.substring( ix, result.length()-5 ) + "ServiceImpl.java";
|
||||||
|
|
||||||
|
String output = System.getProperty( "swagger.codegen.jaxrs.impl.source" );
|
||||||
|
if( output != null ){
|
||||||
|
result = result.replace( apiFileFolder(), implFileFolder(output));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( templateName.endsWith( "Factory.mustache")){
|
||||||
|
int ix = result.lastIndexOf( '/' );
|
||||||
|
result = result.substring( 0, ix ) + "/factories" + result.substring( ix, result.length()-5 ) + "ServiceFactory.java";
|
||||||
|
|
||||||
|
String output = System.getProperty( "swagger.codegen.jaxrs.impl.source" );
|
||||||
|
if( output != null ){
|
||||||
|
result = result.replace( apiFileFolder(), implFileFolder(output));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( templateName.endsWith( "Service.mustache")) {
|
||||||
|
int ix = result.lastIndexOf('.');
|
||||||
|
result = result.substring(0, ix) + "Service.java";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String implFileFolder(String output) {
|
||||||
|
return outputFolder + "/" + output + "/" + apiPackage().replace('.', File.separatorChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldOverwrite( String filename ){
|
||||||
|
|
||||||
|
return !filename.endsWith( "ServiceImpl.java") && !filename.endsWith( "ServiceFactory.java");
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,11 +1,19 @@
|
|||||||
package com.wordnik.swagger.codegen.languages;
|
package com.wordnik.swagger.codegen.languages;
|
||||||
|
|
||||||
import com.wordnik.swagger.codegen.*;
|
|
||||||
import com.wordnik.swagger.util.Json;
|
|
||||||
import com.wordnik.swagger.models.properties.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.wordnik.swagger.codegen.CodegenConfig;
|
||||||
|
import com.wordnik.swagger.codegen.CodegenOperation;
|
||||||
|
import com.wordnik.swagger.codegen.CodegenParameter;
|
||||||
|
import com.wordnik.swagger.codegen.CodegenResponse;
|
||||||
|
import com.wordnik.swagger.codegen.CodegenType;
|
||||||
|
import com.wordnik.swagger.codegen.DefaultCodegen;
|
||||||
|
import com.wordnik.swagger.codegen.SupportingFile;
|
||||||
|
|
||||||
public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig {
|
public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||||
protected String apiVersion = "1.0.0";
|
protected String apiVersion = "1.0.0";
|
||||||
@ -156,8 +164,10 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||||
Map<String, Object> objectMap = (Map<String, Object>)objs.get("operations");
|
@SuppressWarnings("unchecked")
|
||||||
List<CodegenOperation> operations = (List<CodegenOperation>)objectMap.get("operation");
|
Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
|
||||||
for(CodegenOperation operation : operations) {
|
for(CodegenOperation operation : operations) {
|
||||||
operation.httpMethod = operation.httpMethod.toLowerCase();
|
operation.httpMethod = operation.httpMethod.toLowerCase();
|
||||||
List<CodegenParameter> params = operation.allParams;
|
List<CodegenParameter> params = operation.allParams;
|
||||||
@ -170,20 +180,14 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
resp.code = "default";
|
resp.code = "default";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(operation.examples != null && operation.examples.size() > 0) {
|
if(operation.examples != null && !operation.examples.isEmpty()) {
|
||||||
List<Map<String, String>> examples = operation.examples;
|
// Leave application/json* items only
|
||||||
for(int i = examples.size() - 1; i >= 0; i--) {
|
for (Iterator<Map<String, String>> it = operation.examples.iterator(); it.hasNext();) {
|
||||||
Map<String, String> example = examples.get(i);
|
final Map<String, String> example = it.next();
|
||||||
String contentType = example.get("contentType");
|
final String contentType = example.get("contentType");
|
||||||
if(contentType != null && contentType.indexOf("application/json") == 0) {
|
if (contentType == null || !contentType.startsWith("application/json")) {
|
||||||
String jsonExample = example.get("example");
|
it.remove();
|
||||||
if(jsonExample != null) {
|
|
||||||
jsonExample = jsonExample.replaceAll("\\\\n", "\n");
|
|
||||||
example.put("example", jsonExample);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
examples.remove(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,8 +120,8 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
supportingFiles.add(new SupportingFile("SWGApiClient.m", sourceFolder, "SWGApiClient.m"));
|
supportingFiles.add(new SupportingFile("SWGApiClient.m", sourceFolder, "SWGApiClient.m"));
|
||||||
supportingFiles.add(new SupportingFile("SWGFile.h", sourceFolder, "SWGFile.h"));
|
supportingFiles.add(new SupportingFile("SWGFile.h", sourceFolder, "SWGFile.h"));
|
||||||
supportingFiles.add(new SupportingFile("SWGFile.m", sourceFolder, "SWGFile.m"));
|
supportingFiles.add(new SupportingFile("SWGFile.m", sourceFolder, "SWGFile.m"));
|
||||||
supportingFiles.add(new SupportingFile("SWGDate.h", sourceFolder, "SWGDate.h"));
|
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", sourceFolder, "JSONValueTransformer+ISO8601.m"));
|
||||||
supportingFiles.add(new SupportingFile("SWGDate.m", sourceFolder, "SWGDate.m"));
|
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", sourceFolder, "JSONValueTransformer+ISO8601.h"));
|
||||||
supportingFiles.add(new SupportingFile("Podfile.mustache", "", "Podfile"));
|
supportingFiles.add(new SupportingFile("Podfile.mustache", "", "Podfile"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +84,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
typeMapping.put("list", "array");
|
typeMapping.put("list", "array");
|
||||||
|
|
||||||
supportingFiles.add(new SupportingFile("composer.mustache", packagePath, "composer.json"));
|
supportingFiles.add(new SupportingFile("composer.mustache", packagePath, "composer.json"));
|
||||||
|
supportingFiles.add(new SupportingFile("configuration.mustache", packagePath + "/lib", "Configuration.php"));
|
||||||
supportingFiles.add(new SupportingFile("APIClient.mustache", packagePath + "/lib", "APIClient.php"));
|
supportingFiles.add(new SupportingFile("APIClient.mustache", packagePath + "/lib", "APIClient.php"));
|
||||||
supportingFiles.add(new SupportingFile("APIClientException.mustache", packagePath + "/lib", "APIClientException.php"));
|
supportingFiles.add(new SupportingFile("APIClientException.mustache", packagePath + "/lib", "APIClientException.php"));
|
||||||
supportingFiles.add(new SupportingFile("require.mustache", packagePath, invokerPackage + ".php"));
|
supportingFiles.add(new SupportingFile("require.mustache", packagePath, invokerPackage + ".php"));
|
||||||
|
@ -34,13 +34,12 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
apiTemplateFiles.put("api.mustache", ".py");
|
apiTemplateFiles.put("api.mustache", ".py");
|
||||||
templateDir = "python";
|
templateDir = "python";
|
||||||
|
|
||||||
apiPackage = invokerPackage;
|
apiPackage = invokerPackage + ".apis";
|
||||||
modelPackage = invokerPackage + ".models";
|
modelPackage = invokerPackage + ".models";
|
||||||
|
|
||||||
languageSpecificPrimitives.clear();
|
languageSpecificPrimitives.clear();
|
||||||
languageSpecificPrimitives.add("int");
|
languageSpecificPrimitives.add("int");
|
||||||
languageSpecificPrimitives.add("float");
|
languageSpecificPrimitives.add("float");
|
||||||
languageSpecificPrimitives.add("long");
|
|
||||||
languageSpecificPrimitives.add("list");
|
languageSpecificPrimitives.add("list");
|
||||||
languageSpecificPrimitives.add("bool");
|
languageSpecificPrimitives.add("bool");
|
||||||
languageSpecificPrimitives.add("str");
|
languageSpecificPrimitives.add("str");
|
||||||
@ -49,7 +48,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
typeMapping.clear();
|
typeMapping.clear();
|
||||||
typeMapping.put("integer", "int");
|
typeMapping.put("integer", "int");
|
||||||
typeMapping.put("float", "float");
|
typeMapping.put("float", "float");
|
||||||
typeMapping.put("long", "long");
|
typeMapping.put("long", "int");
|
||||||
typeMapping.put("double", "float");
|
typeMapping.put("double", "float");
|
||||||
typeMapping.put("array", "list");
|
typeMapping.put("array", "list");
|
||||||
typeMapping.put("map", "map");
|
typeMapping.put("map", "map");
|
||||||
@ -70,8 +69,11 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
supportingFiles.add(new SupportingFile("README.mustache", eggPackage, "README.md"));
|
supportingFiles.add(new SupportingFile("README.mustache", eggPackage, "README.md"));
|
||||||
supportingFiles.add(new SupportingFile("setup.mustache", eggPackage, "setup.py"));
|
supportingFiles.add(new SupportingFile("setup.mustache", eggPackage, "setup.py"));
|
||||||
supportingFiles.add(new SupportingFile("swagger.mustache", invokerPackage, "swagger.py"));
|
supportingFiles.add(new SupportingFile("swagger.mustache", invokerPackage, "swagger.py"));
|
||||||
|
supportingFiles.add(new SupportingFile("rest.mustache", invokerPackage, "rest.py"));
|
||||||
|
supportingFiles.add(new SupportingFile("util.mustache", invokerPackage, "util.py"));
|
||||||
supportingFiles.add(new SupportingFile("__init__package.mustache", invokerPackage, "__init__.py"));
|
supportingFiles.add(new SupportingFile("__init__package.mustache", invokerPackage, "__init__.py"));
|
||||||
supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage.replace('.', File.separatorChar), "__init__.py"));
|
supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage.replace('.', File.separatorChar), "__init__.py"));
|
||||||
|
supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage.replace('.', File.separatorChar), "__init__.py"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -113,9 +115,9 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
if(languageSpecificPrimitives.contains(type)) {
|
if(languageSpecificPrimitives.contains(type)) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
type = toModelName(swaggerType);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
type = swaggerType;
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,9 +135,9 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
if (name.matches("^[A-Z_]*$"))
|
if (name.matches("^[A-Z_]*$"))
|
||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
|
|
||||||
// camelize (lower first character) the variable name
|
// underscore the variable name
|
||||||
// petId => pet_id
|
// petId => pet_id
|
||||||
name = underscore(name);
|
name = underscore(dropDots(name));
|
||||||
|
|
||||||
// for reserved word or word starting with number, append _
|
// for reserved word or word starting with number, append _
|
||||||
if(reservedWords.contains(name) || name.matches("^\\d.*"))
|
if(reservedWords.contains(name) || name.matches("^\\d.*"))
|
||||||
@ -144,6 +146,10 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String dropDots(String str) {
|
||||||
|
return str.replaceAll("\\.", "_");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toParamName(String name) {
|
public String toParamName(String name) {
|
||||||
// should be the same as variable name
|
// should be the same as variable name
|
||||||
@ -168,8 +174,8 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
|
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
|
||||||
|
|
||||||
// underscore the model file name
|
// underscore the model file name
|
||||||
// PhoneNumber.rb => phone_number.rb
|
// PhoneNumber => phone_number
|
||||||
return underscore(name);
|
return underscore(dropDots(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -8,10 +8,9 @@ import java.util.*;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||||
protected String invokerPackage = "com.wordnik.client";
|
protected String gemName = "swagger_client";
|
||||||
protected String groupId = "com.wordnik";
|
protected String moduleName = null;
|
||||||
protected String artifactId = "swagger-client";
|
protected String libFolder = "lib";
|
||||||
protected String artifactVersion = "1.0.0";
|
|
||||||
|
|
||||||
public CodegenType getTag() {
|
public CodegenType getTag() {
|
||||||
return CodegenType.CLIENT;
|
return CodegenType.CLIENT;
|
||||||
@ -25,10 +24,18 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
return "Generates a Ruby client library.";
|
return "Generates a Ruby client library.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate Ruby module name from the gem name, e.g. use "SwaggerClient" for "swagger_client".
|
||||||
|
*/
|
||||||
|
public String generateModuleName() {
|
||||||
|
return camelize(gemName.replaceAll("[^\\w]+", "_"));
|
||||||
|
}
|
||||||
|
|
||||||
public RubyClientCodegen() {
|
public RubyClientCodegen() {
|
||||||
super();
|
super();
|
||||||
modelPackage = "models";
|
moduleName = generateModuleName();
|
||||||
apiPackage = "lib";
|
modelPackage = gemName + "/models";
|
||||||
|
apiPackage = gemName + "/api";
|
||||||
outputFolder = "generated-code/ruby";
|
outputFolder = "generated-code/ruby";
|
||||||
modelTemplateFiles.put("model.mustache", ".rb");
|
modelTemplateFiles.put("model.mustache", ".rb");
|
||||||
apiTemplateFiles.put("api.mustache", ".rb");
|
apiTemplateFiles.put("api.mustache", ".rb");
|
||||||
@ -39,17 +46,15 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
|
|
||||||
reservedWords = new HashSet<String> (
|
reservedWords = new HashSet<String> (
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
|
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
|
||||||
"begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN",
|
"begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN",
|
||||||
"break", "do", "false", "next", "rescue", "then", "when", "END", "case",
|
"break", "do", "false", "next", "rescue", "then", "when", "END", "case",
|
||||||
"else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif",
|
"else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif",
|
||||||
"if", "not", "return", "undef", "yield")
|
"if", "not", "return", "undef", "yield")
|
||||||
);
|
);
|
||||||
|
|
||||||
additionalProperties.put("invokerPackage", invokerPackage);
|
additionalProperties.put("gemName", gemName);
|
||||||
additionalProperties.put("groupId", groupId);
|
additionalProperties.put("moduleName", moduleName);
|
||||||
additionalProperties.put("artifactId", artifactId);
|
|
||||||
additionalProperties.put("artifactVersion", artifactVersion);
|
|
||||||
|
|
||||||
languageSpecificPrimitives.add("int");
|
languageSpecificPrimitives.add("int");
|
||||||
languageSpecificPrimitives.add("array");
|
languageSpecificPrimitives.add("array");
|
||||||
@ -64,15 +69,18 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
typeMapping.put("List", "array");
|
typeMapping.put("List", "array");
|
||||||
typeMapping.put("map", "map");
|
typeMapping.put("map", "map");
|
||||||
|
|
||||||
supportingFiles.add(new SupportingFile("swagger-client.gemspec.mustache", "", "swagger-client.gemspec"));
|
String baseFolder = "lib/" + gemName;
|
||||||
supportingFiles.add(new SupportingFile("swagger-client.mustache", "", "lib/swagger-client.rb"));
|
String swaggerFolder = baseFolder + "/swagger";
|
||||||
supportingFiles.add(new SupportingFile("swagger.mustache", "", "lib/swagger.rb"));
|
String modelFolder = baseFolder + "/models";
|
||||||
supportingFiles.add(new SupportingFile("monkey.mustache", "", "lib/monkey.rb"));
|
supportingFiles.add(new SupportingFile("swagger_client.gemspec.mustache", "", gemName + ".gemspec"));
|
||||||
supportingFiles.add(new SupportingFile("swagger/request.mustache", "", "lib/swagger/request.rb"));
|
supportingFiles.add(new SupportingFile("swagger_client.mustache", "lib", gemName + ".rb"));
|
||||||
supportingFiles.add(new SupportingFile("swagger/response.mustache", "", "lib/swagger/response.rb"));
|
supportingFiles.add(new SupportingFile("monkey.mustache", baseFolder, "monkey.rb"));
|
||||||
supportingFiles.add(new SupportingFile("swagger/version.mustache", "", "lib/swagger/version.rb"));
|
supportingFiles.add(new SupportingFile("swagger.mustache", baseFolder, "swagger.rb"));
|
||||||
supportingFiles.add(new SupportingFile("swagger/configuration.mustache", "", "lib/swagger/configuration.rb"));
|
supportingFiles.add(new SupportingFile("swagger/request.mustache", swaggerFolder, "request.rb"));
|
||||||
supportingFiles.add(new SupportingFile("base_object.mustache", "", "models/base_object.rb"));
|
supportingFiles.add(new SupportingFile("swagger/response.mustache", swaggerFolder, "response.rb"));
|
||||||
|
supportingFiles.add(new SupportingFile("swagger/version.mustache", swaggerFolder, "version.rb"));
|
||||||
|
supportingFiles.add(new SupportingFile("swagger/configuration.mustache", swaggerFolder, "configuration.rb"));
|
||||||
|
supportingFiles.add(new SupportingFile("base_object.mustache", modelFolder, "base_object.rb"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -82,11 +90,11 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String apiFileFolder() {
|
public String apiFileFolder() {
|
||||||
return outputFolder + "/" + apiPackage().replace('.', File.separatorChar);
|
return outputFolder + File.separatorChar + "lib" + File.separatorChar + gemName + File.separatorChar + "api";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String modelFileFolder() {
|
public String modelFileFolder() {
|
||||||
return outputFolder + "/" + modelPackage().replace('.', File.separatorChar);
|
return outputFolder + File.separatorChar + "lib" + File.separatorChar + gemName + File.separatorChar + "models";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -150,13 +158,13 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
// should be the same as variable name
|
// should be the same as variable name
|
||||||
return toVarName(name);
|
return toVarName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toModelName(String name) {
|
public String toModelName(String name) {
|
||||||
// model name cannot use reserved keyword, e.g. return
|
// model name cannot use reserved keyword, e.g. return
|
||||||
if(reservedWords.contains(name))
|
if(reservedWords.contains(name))
|
||||||
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
|
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
|
||||||
|
|
||||||
// camelize the model name
|
// camelize the model name
|
||||||
// phone_number => PhoneNumber
|
// phone_number => PhoneNumber
|
||||||
return camelize(name);
|
return camelize(name);
|
||||||
@ -167,11 +175,11 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
// model name cannot use reserved keyword, e.g. return
|
// model name cannot use reserved keyword, e.g. return
|
||||||
if(reservedWords.contains(name))
|
if(reservedWords.contains(name))
|
||||||
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
|
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
|
||||||
|
|
||||||
// underscore the model file name
|
// underscore the model file name
|
||||||
// PhoneNumber.rb => phone_number.rb
|
// PhoneNumber.rb => phone_number.rb
|
||||||
return underscore(name);
|
return underscore(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toApiFilename(String name) {
|
public String toApiFilename(String name) {
|
||||||
@ -186,7 +194,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
public String toApiName(String name) {
|
public String toApiName(String name) {
|
||||||
if(name.length() == 0)
|
if(name.length() == 0)
|
||||||
return "DefaultApi";
|
return "DefaultApi";
|
||||||
// e.g. phone_number_api => PhoneNumberApi
|
// e.g. phone_number_api => PhoneNumberApi
|
||||||
return camelize(name) + "Api";
|
return camelize(name) + "Api";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,8 +204,17 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
|
|||||||
if(reservedWords.contains(operationId))
|
if(reservedWords.contains(operationId))
|
||||||
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
|
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
|
||||||
|
|
||||||
return underscore(operationId);
|
return underscore(operationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toModelImport(String name) {
|
||||||
|
return modelPackage() + "/" + toModelFilename(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toApiImport(String name) {
|
||||||
|
return apiPackage() + "/" + toApiFilename(name);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package {{package}};
|
package {{package}};
|
||||||
|
|
||||||
import {{modelPackage}}.*;
|
import {{modelPackage}}.*;
|
||||||
|
import {{package}}.{{classname}}Service;
|
||||||
|
import {{package}}.factories.{{classname}}ServiceFactory;
|
||||||
|
|
||||||
import com.wordnik.swagger.annotations.ApiParam;
|
import com.wordnik.swagger.annotations.ApiParam;
|
||||||
|
|
||||||
@ -21,26 +23,31 @@ import javax.ws.rs.core.Response;
|
|||||||
import javax.ws.rs.*;
|
import javax.ws.rs.*;
|
||||||
|
|
||||||
@Path("/{{baseName}}")
|
@Path("/{{baseName}}")
|
||||||
|
{{#hasConsumes}}@Consumes({ {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }){{/hasConsumes}}
|
||||||
|
{{#hasProduces}}@Produces({ {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }){{/hasProduces}}
|
||||||
@com.wordnik.swagger.annotations.Api(value = "/{{baseName}}", description = "the {{baseName}} API")
|
@com.wordnik.swagger.annotations.Api(value = "/{{baseName}}", description = "the {{baseName}} API")
|
||||||
{{#operations}}
|
{{#operations}}
|
||||||
public class {{classname}} {
|
public class {{classname}} {
|
||||||
{{#operation}}
|
|
||||||
@{{httpMethod}}
|
|
||||||
{{#subresourceOperation}}@Path("{{path}}"){{/subresourceOperation}}
|
|
||||||
{{#hasConsumes}}@Consumes({ {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }){{/hasConsumes}}
|
|
||||||
{{#hasProduces}}@Produces({ {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }){{/hasProduces}}
|
|
||||||
@com.wordnik.swagger.annotations.ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}", response = {{{returnType}}}.class{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}})
|
|
||||||
@com.wordnik.swagger.annotations.ApiResponses(value = { {{#responses}}
|
|
||||||
@com.wordnik.swagger.annotations.ApiResponse(code = {{{code}}}, message = "{{{message}}}"){{#hasMore}},
|
|
||||||
{{/hasMore}}{{/responses}} })
|
|
||||||
|
|
||||||
public Response {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},
|
private final {{classname}}Service delegate = {{classname}}ServiceFactory.get{{classname}}();
|
||||||
|
|
||||||
|
{{#operation}}
|
||||||
|
@{{httpMethod}}
|
||||||
|
{{#subresourceOperation}}@Path("{{path}}"){{/subresourceOperation}}
|
||||||
|
{{#hasConsumes}}@Consumes({ {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }){{/hasConsumes}}
|
||||||
|
{{#hasProduces}}@Produces({ {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }){{/hasProduces}}
|
||||||
|
@com.wordnik.swagger.annotations.ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}", response = {{{returnType}}}.class{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}})
|
||||||
|
@com.wordnik.swagger.annotations.ApiResponses(value = { {{#responses}}
|
||||||
|
@com.wordnik.swagger.annotations.ApiResponse(code = {{{code}}}, message = "{{{message}}}"){{#hasMore}},
|
||||||
|
{{/hasMore}}{{/responses}} })
|
||||||
|
|
||||||
|
public Response {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},
|
||||||
{{/hasMore}}{{/allParams}})
|
{{/hasMore}}{{/allParams}})
|
||||||
throws NotFoundException {
|
throws NotFoundException {
|
||||||
// do some magic!
|
// do some magic!
|
||||||
return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
|
return delegate.{{nickname}}({{#allParams}}{{#isFile}}fileDetail{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}{{#hasMore}},{{/hasMore}}{{/allParams}});
|
||||||
}
|
}
|
||||||
|
{{/operation}}
|
||||||
{{/operation}}
|
|
||||||
}
|
}
|
||||||
{{/operations}}
|
{{/operations}}
|
||||||
|
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package {{package}};
|
||||||
|
|
||||||
|
import {{package}}.*;
|
||||||
|
import {{modelPackage}}.*;
|
||||||
|
|
||||||
|
import com.sun.jersey.multipart.FormDataParam;
|
||||||
|
|
||||||
|
{{#imports}}import {{import}};
|
||||||
|
{{/imports}}
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import {{package}}.NotFoundException;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import com.sun.jersey.core.header.FormDataContentDisposition;
|
||||||
|
import com.sun.jersey.multipart.FormDataParam;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
{{#operations}}
|
||||||
|
public abstract class {{classname}}Service {
|
||||||
|
{{#operation}}
|
||||||
|
public abstract Response {{nickname}}({{#allParams}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}}{{#hasMore}},{{/hasMore}}{{/allParams}})
|
||||||
|
throws NotFoundException;
|
||||||
|
{{/operation}}
|
||||||
|
}
|
||||||
|
{{/operations}}
|
@ -0,0 +1,14 @@
|
|||||||
|
package {{package}}.factories;
|
||||||
|
|
||||||
|
import {{package}}.{{classname}}Service;
|
||||||
|
import {{package}}.impl.{{classname}}ServiceImpl;
|
||||||
|
|
||||||
|
public class {{classname}}ServiceFactory {
|
||||||
|
|
||||||
|
private final static {{classname}}Service service = new {{classname}}ServiceImpl();
|
||||||
|
|
||||||
|
public static {{classname}}Service get{{classname}}()
|
||||||
|
{
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package {{package}}.impl;
|
||||||
|
|
||||||
|
import {{package}}.*;
|
||||||
|
import {{modelPackage}}.*;
|
||||||
|
|
||||||
|
import com.sun.jersey.multipart.FormDataParam;
|
||||||
|
|
||||||
|
{{#imports}}import {{import}};
|
||||||
|
{{/imports}}
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import {{package}}.NotFoundException;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import com.sun.jersey.core.header.FormDataContentDisposition;
|
||||||
|
import com.sun.jersey.multipart.FormDataParam;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
{{#operations}}
|
||||||
|
public class {{classname}}ServiceImpl extends {{classname}}Service {
|
||||||
|
{{#operation}}
|
||||||
|
@Override
|
||||||
|
public Response {{nickname}}({{#allParams}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}}{{#hasMore}},{{/hasMore}}{{/allParams}})
|
||||||
|
throws NotFoundException {
|
||||||
|
// do some magic!
|
||||||
|
return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
|
||||||
|
}
|
||||||
|
{{/operation}}
|
||||||
|
}
|
||||||
|
{{/operations}}
|
@ -62,6 +62,25 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>build-helper-maven-plugin</artifactId>
|
||||||
|
<version>1.9.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>add-source</id>
|
||||||
|
<phase>generate-sources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-source</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<sources>
|
||||||
|
<source>src/gen/java</source>
|
||||||
|
</sources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -129,7 +148,7 @@
|
|||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<properties>
|
<properties>
|
||||||
<swagger-core-version>1.5.2-M2-SNAPSHOT</swagger-core-version>
|
<swagger-core-version>1.5.2-M2</swagger-core-version>
|
||||||
<jetty-version>9.2.9.v20150224</jetty-version>
|
<jetty-version>9.2.9.v20150224</jetty-version>
|
||||||
<jersey-version>1.13</jersey-version>
|
<jersey-version>1.13</jersey-version>
|
||||||
<slf4j-version>1.6.3</slf4j-version>
|
<slf4j-version>1.6.3</slf4j-version>
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
{{#isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}
|
@ -0,0 +1 @@
|
|||||||
|
{{#isFormParam}}{{#notFile}}{{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}FormDataContentDisposition fileDetail{{/isFile}}{{/isFormParam}}
|
@ -0,0 +1 @@
|
|||||||
|
{{#isHeaderParam}}{{{dataType}}} {{paramName}}{{/isHeaderParam}}
|
@ -0,0 +1 @@
|
|||||||
|
{{#isPathParam}}{{{dataType}}} {{paramName}}{{/isPathParam}}
|
@ -0,0 +1 @@
|
|||||||
|
{{#isQueryParam}}{{{dataType}}} {{paramName}}{{/isQueryParam}}
|
@ -1,2 +1,2 @@
|
|||||||
{{#isFormParam}}{{#notFile}}
|
{{#isFormParam}}{{#notFile}}
|
||||||
@ApiParam(value = "{{{description}}}"{{#required}}, required=true{{/required}} {{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}})@RequestPart("{{paramName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}@ApiParam(value = "file detail") @RequestPart("file") MultipartFile fileDetail{{/isFile}}{{/isFormParam}}
|
@ApiParam(value = "{{{description}}}"{{#required}}, required=true{{/required}} {{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @RequestPart(value="{{paramName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}}) {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}@ApiParam(value = "file detail") @RequestPart("file") MultipartFile fileDetail{{/isFile}}{{/isFormParam}}
|
@ -1 +1 @@
|
|||||||
{{#isHeaderParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}})@RequestHeader("{{paramName}}") {{{dataType}}} {{paramName}}{{/isHeaderParam}}
|
{{#isHeaderParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @RequestHeader(value="{{paramName}}", required={{#required}}true{{/required}}{{^required}}false{{/required}}) {{{dataType}}} {{paramName}}{{/isHeaderParam}}
|
||||||
|
@ -1 +1 @@
|
|||||||
{{#isQueryParam}}@ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, allowableValues = "{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue = "{{{defaultValue}}}"{{/defaultValue}}) @RequestParam(value = "{{paramName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{{dataType}}} {{paramName}}{{/isQueryParam}}
|
{{#isQueryParam}}@ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, allowableValues = "{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue = "{{{defaultValue}}}"{{/defaultValue}}) @RequestParam(value = "{{paramName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{{dataType}}} {{paramName}}{{/isQueryParam}}
|
||||||
|
@ -19,3 +19,4 @@ com.wordnik.swagger.codegen.languages.StaticHtmlGenerator
|
|||||||
com.wordnik.swagger.codegen.languages.SwaggerGenerator
|
com.wordnik.swagger.codegen.languages.SwaggerGenerator
|
||||||
com.wordnik.swagger.codegen.languages.SwaggerYamlGenerator
|
com.wordnik.swagger.codegen.languages.SwaggerYamlGenerator
|
||||||
com.wordnik.swagger.codegen.languages.TizenClientCodegen
|
com.wordnik.swagger.codegen.languages.TizenClientCodegen
|
||||||
|
com.wordnik.swagger.codegen.languages.AkkaScalaClientCodegen
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package {{package}}
|
||||||
|
|
||||||
|
{{#imports}}
|
||||||
|
import {{import}}
|
||||||
|
{{/imports}}
|
||||||
|
import {{invokerPackage}}._
|
||||||
|
import {{invokerPackage}}.CollectionFormats._
|
||||||
|
import {{invokerPackage}}.ApiKeyLocations._
|
||||||
|
|
||||||
|
{{#operations}}
|
||||||
|
object {{classname}} {
|
||||||
|
|
||||||
|
{{#operation}}
|
||||||
|
{{#javadocRenderer}}
|
||||||
|
{{>javadoc}}
|
||||||
|
{{/javadocRenderer}}
|
||||||
|
def {{operationId}}({{>methodParameters}}): ApiRequest[{{>operationReturnType}}] =
|
||||||
|
ApiRequest[{{>operationReturnType}}](ApiMethods.{{httpMethod.toUpperCase}}, "{{basePath}}", "{{path}}", {{#consumes.0}}"{{mediaType}}"{{/consumes.0}}{{^consumes}}"application/json"{{/consumes}})
|
||||||
|
{{#authMethods}}{{#isApiKey}}.withApiKey(apiKey, "{{keyParamName}}", {{#isKeyInQuery}}QUERY{{/isKeyInQuery}}{{#isKeyInHeader}}HEADER{{/isKeyInHeader}})
|
||||||
|
{{/isApiKey}}{{#isBasic}}.withCredentials(basicAuth)
|
||||||
|
{{/isBasic}}{{/authMethods}}{{#bodyParam}}.withBody({{paramName}})
|
||||||
|
{{/bodyParam}}{{#formParams}}.withFormParam({{>paramCreation}})
|
||||||
|
{{/formParams}}{{#queryParams}}.withQueryParam({{>paramCreation}})
|
||||||
|
{{/queryParams}}{{#pathParams}}.withPathParam({{>paramCreation}})
|
||||||
|
{{/pathParams}}{{#headerParams}}.withHeaderParam({{>paramCreation}})
|
||||||
|
{{/headerParams}}{{#responses}}{{^isWildcard}}{{#dataType}}.with{{>responseState}}Response[{{dataType}}]({{code}})
|
||||||
|
{{/dataType}}{{^dataType}}.with{{>responseState}}Response[Unit]({{code}})
|
||||||
|
{{/dataType}}{{/isWildcard}}{{/responses}}{{#responses}}{{#isWildcard}}{{#dataType}}.withDefault{{>responseState}}Response[{{dataType}}]
|
||||||
|
{{/dataType}}{{^dataType}}.withDefault{{>responseState}}Response[Unit]
|
||||||
|
{{/dataType}}{{/isWildcard}}{{/responses}}{{^responseHeaders.isEmpty}}
|
||||||
|
object {{#fnCapitalize}}{{operationId}}{{/fnCapitalize}}Headers { {{#responseHeaders}}
|
||||||
|
def {{name}}(r: ApiReturnWithHeaders) = r.get{{^isContainer}}{{baseType}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}Header("{{baseName}}"){{/responseHeaders}}
|
||||||
|
}
|
||||||
|
{{/responseHeaders.isEmpty}}
|
||||||
|
{{/operation}}
|
||||||
|
|
||||||
|
{{#unknownStatusCodes}}
|
||||||
|
ApiInvoker.addCustomStatusCode({{value}}, isSuccess = false)
|
||||||
|
{{/unknownStatusCodes}}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/operations}}
|
@ -0,0 +1,323 @@
|
|||||||
|
package {{invokerPackage}}
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import javax.net.ssl._
|
||||||
|
|
||||||
|
import akka.actor.ActorSystem
|
||||||
|
import akka.io.IO
|
||||||
|
import akka.pattern.ask
|
||||||
|
import akka.util.Timeout
|
||||||
|
import org.joda.time.DateTime
|
||||||
|
import org.joda.time.format.ISODateTimeFormat
|
||||||
|
import org.json4s.JsonAST.JString
|
||||||
|
import org.json4s._
|
||||||
|
import org.json4s.jackson.JsonMethods._
|
||||||
|
import org.json4s.jackson.Serialization
|
||||||
|
import spray.can.Http
|
||||||
|
import spray.can.Http.HostConnectorSetup
|
||||||
|
import spray.client.pipelining
|
||||||
|
import spray.client.pipelining._
|
||||||
|
import spray.http.HttpEncodings._
|
||||||
|
import spray.http.HttpHeaders.{RawHeader, `Accept-Encoding`}
|
||||||
|
import spray.http.Uri.Query
|
||||||
|
import spray.http._
|
||||||
|
import spray.http.parser.HttpParser
|
||||||
|
import spray.httpx.encoding.{Deflate, Encoder, Gzip}
|
||||||
|
import spray.httpx.unmarshalling._
|
||||||
|
import spray.io.ClientSSLEngineProvider
|
||||||
|
|
||||||
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
|
import scala.reflect.ClassTag
|
||||||
|
import scala.util.control.NonFatal
|
||||||
|
|
||||||
|
object ApiInvoker {
|
||||||
|
|
||||||
|
def apply()(implicit system: ActorSystem): ApiInvoker =
|
||||||
|
apply(DefaultFormats + DateTimeSerializer)
|
||||||
|
def apply(serializers: Traversable[Serializer[_]])(implicit system: ActorSystem): ApiInvoker =
|
||||||
|
apply(DefaultFormats + DateTimeSerializer ++ serializers)
|
||||||
|
def apply(formats: Formats)(implicit system: ActorSystem): ApiInvoker = new ApiInvoker(formats)
|
||||||
|
|
||||||
|
case class CustomStatusCode(value: Int, reason: String = "Application-defined status code", isSuccess: Boolean = true)
|
||||||
|
|
||||||
|
def addCustomStatusCode(code: CustomStatusCode): Unit = addCustomStatusCode(code.value, code.reason, code.isSuccess)
|
||||||
|
|
||||||
|
def addCustomStatusCode(code: Int, reason: String = "Application defined code", isSuccess: Boolean = true) = {
|
||||||
|
StatusCodes.getForKey(code) foreach { c =>
|
||||||
|
StatusCodes.registerCustom(code, reason, reason, isSuccess, allowsEntity = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows request execution without calling apiInvoker.execute(request)
|
||||||
|
* request.response can be used to get a future of the ApiResponse generated.
|
||||||
|
* request.result can be used to get a future of the expected ApiResponse content. If content doesn't match, a
|
||||||
|
* Future will failed with a ClassCastException
|
||||||
|
* @param request the apiRequest to be executed
|
||||||
|
*/
|
||||||
|
implicit class ApiRequestImprovements[T](request: ApiRequest[T]) {
|
||||||
|
|
||||||
|
def response(invoker: ApiInvoker)(implicit ec: ExecutionContext, system: ActorSystem): Future[ApiResponse[T]] =
|
||||||
|
response(ec, system, invoker)
|
||||||
|
|
||||||
|
def response(implicit ec: ExecutionContext, system: ActorSystem, invoker: ApiInvoker): Future[ApiResponse[T]] =
|
||||||
|
invoker.execute(request)
|
||||||
|
|
||||||
|
def result[U <: T](implicit c: ClassTag[U], ec: ExecutionContext, system: ActorSystem, invoker: ApiInvoker): Future[U] =
|
||||||
|
invoker.execute(request).map(_.content).mapTo[U]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows transformation from ApiMethod to spray HttpMethods
|
||||||
|
* @param method the ApiMethod to be converted
|
||||||
|
*/
|
||||||
|
implicit class ApiMethodExtensions(val method: ApiMethod) {
|
||||||
|
def toSprayMethod: HttpMethod = HttpMethods.getForKey(method.value).getOrElse(HttpMethods.GET)
|
||||||
|
}
|
||||||
|
|
||||||
|
case object DateTimeSerializer extends CustomSerializer[DateTime](format => ( {
|
||||||
|
case JString(s) =>
|
||||||
|
ISODateTimeFormat.dateTimeParser().parseDateTime(s)
|
||||||
|
}, {
|
||||||
|
case d: DateTime =>
|
||||||
|
JString(ISODateTimeFormat.dateTimeParser().print(d))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends UntrustedSslContext with CustomContentTypes {
|
||||||
|
|
||||||
|
import io.swagger.client.core.ApiInvoker._
|
||||||
|
import io.swagger.client.core.ParametersMap._
|
||||||
|
|
||||||
|
implicit val ec = system.dispatcher
|
||||||
|
implicit val jsonFormats = formats
|
||||||
|
|
||||||
|
def settings = ApiSettings(system)
|
||||||
|
|
||||||
|
import spray.http.MessagePredicate._
|
||||||
|
|
||||||
|
val CompressionFilter = MessagePredicate({ _ => settings.compressionEnabled}) &&
|
||||||
|
Encoder.DefaultFilter &&
|
||||||
|
minEntitySize(settings.compressionSizeThreshold)
|
||||||
|
|
||||||
|
settings.customCodes.foreach(addCustomStatusCode)
|
||||||
|
|
||||||
|
private def addAuthentication(credentialsSeq: Seq[Credentials]): pipelining.RequestTransformer =
|
||||||
|
request =>
|
||||||
|
credentialsSeq.foldLeft(request) {
|
||||||
|
case (req, BasicCredentials(login, password)) =>
|
||||||
|
req ~> addCredentials(BasicHttpCredentials(login, password))
|
||||||
|
case (req, ApiKeyCredentials(keyValue, keyName, ApiKeyLocations.HEADER)) =>
|
||||||
|
req ~> addHeader(RawHeader(keyName, keyValue.value))
|
||||||
|
case (req, _) => req
|
||||||
|
}
|
||||||
|
|
||||||
|
private def addHeaders(headers: Map[String, Any]): pipelining.RequestTransformer = { request =>
|
||||||
|
|
||||||
|
val rawHeaders = for {
|
||||||
|
(name, value) <- headers.asFormattedParams
|
||||||
|
header = RawHeader(name, String.valueOf(value))
|
||||||
|
} yield header
|
||||||
|
|
||||||
|
request.withHeaders(rawHeaders.toList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def bodyPart(name: String, value: Any): BodyPart = {
|
||||||
|
value match {
|
||||||
|
case f: File =>
|
||||||
|
BodyPart(f, name)
|
||||||
|
case v: String =>
|
||||||
|
BodyPart(HttpEntity(String.valueOf(v)))
|
||||||
|
case NumericValue(v) =>
|
||||||
|
BodyPart(HttpEntity(String.valueOf(v)))
|
||||||
|
case m: ApiModel =>
|
||||||
|
BodyPart(HttpEntity(Serialization.write(m)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def formDataContent(request: ApiRequest[_]) = {
|
||||||
|
val params = request.formParams.asFormattedParams
|
||||||
|
if (params.isEmpty)
|
||||||
|
None
|
||||||
|
else
|
||||||
|
Some(
|
||||||
|
normalizedContentType(request.contentType).mediaType match {
|
||||||
|
case MediaTypes.`multipart/form-data` =>
|
||||||
|
MultipartFormData(params.map { case (name, value) => (name, bodyPart(name, value))})
|
||||||
|
case MediaTypes.`application/x-www-form-urlencoded` =>
|
||||||
|
FormData(params.mapValues(String.valueOf))
|
||||||
|
case m: MediaType => // Default : application/x-www-form-urlencoded.
|
||||||
|
FormData(params.mapValues(String.valueOf))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def bodyContent(request: ApiRequest[_]): Option[Any] = {
|
||||||
|
request.bodyParam.map(Extraction.decompose).map(compact)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def createRequest(uri: Uri, request: ApiRequest[_]): HttpRequest = {
|
||||||
|
|
||||||
|
val builder = new RequestBuilder(request.method.toSprayMethod)
|
||||||
|
val httpRequest = request.method.toSprayMethod match {
|
||||||
|
case HttpMethods.GET | HttpMethods.DELETE => builder.apply(uri)
|
||||||
|
case HttpMethods.POST | HttpMethods.PUT =>
|
||||||
|
formDataContent(request) orElse bodyContent(request) match {
|
||||||
|
case Some(c: FormData) =>
|
||||||
|
builder.apply(uri, c)
|
||||||
|
case Some(c: MultipartFormData) =>
|
||||||
|
builder.apply(uri, c)
|
||||||
|
case Some(c: String) =>
|
||||||
|
builder.apply(uri, HttpEntity(normalizedContentType(request.contentType), c))
|
||||||
|
case _ =>
|
||||||
|
builder.apply(uri, HttpEntity(normalizedContentType(request.contentType), " "))
|
||||||
|
}
|
||||||
|
case _ => builder.apply(uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
httpRequest ~>
|
||||||
|
addHeaders(request.headerParams) ~>
|
||||||
|
addAuthentication(request.credentials) ~>
|
||||||
|
encode(Gzip(CompressionFilter))
|
||||||
|
}
|
||||||
|
|
||||||
|
def makeQuery(r: ApiRequest[_]): Query = {
|
||||||
|
r.credentials.foldLeft(r.queryParams) {
|
||||||
|
case (params, ApiKeyCredentials(key, keyName, ApiKeyLocations.QUERY)) =>
|
||||||
|
params + (keyName -> key.value)
|
||||||
|
case (params, _) => params
|
||||||
|
}.asFormattedParams
|
||||||
|
.mapValues(String.valueOf)
|
||||||
|
.foldRight[Query](Uri.Query.Empty) {
|
||||||
|
case ((name, value), acc) => acc.+:(name, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def makeUri(r: ApiRequest[_]): Uri = {
|
||||||
|
val opPath = r.operationPath.replaceAll("\\{format\\}", "json")
|
||||||
|
val opPathWithParams = r.pathParams.asFormattedParams
|
||||||
|
.mapValues(String.valueOf)
|
||||||
|
.foldLeft(opPath) {
|
||||||
|
case (path, (name, value)) => path.replaceAll(s"\\{$name\\}", value)
|
||||||
|
}
|
||||||
|
val query = makeQuery(r)
|
||||||
|
|
||||||
|
Uri(r.basePath + opPathWithParams).withQuery(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute[T](r: ApiRequest[T]): Future[ApiResponse[T]] = {
|
||||||
|
try {
|
||||||
|
implicit val timeout: Timeout = settings.connectionTimeout
|
||||||
|
|
||||||
|
val uri = makeUri(r)
|
||||||
|
|
||||||
|
val connector = HostConnectorSetup(
|
||||||
|
uri.authority.host.toString,
|
||||||
|
uri.effectivePort,
|
||||||
|
sslEncryption = "https".equals(uri.scheme),
|
||||||
|
defaultHeaders = settings.defaultHeaders ++ List(`Accept-Encoding`(gzip, deflate)))
|
||||||
|
|
||||||
|
val request = createRequest(uri, r)
|
||||||
|
|
||||||
|
for {
|
||||||
|
Http.HostConnectorInfo(hostConnector, _) <- IO(Http) ? connector
|
||||||
|
response <- hostConnector.ask(request).mapTo[HttpResponse]
|
||||||
|
} yield {
|
||||||
|
response ~> decode(Deflate) ~> decode(Gzip) ~> unmarshallApiResponse(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
case NonFatal(x) => Future.failed(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def unmarshallApiResponse[T](request: ApiRequest[T])(response: HttpResponse): ApiResponse[T] = {
|
||||||
|
request.responseForCode(response.status.intValue) match {
|
||||||
|
case Some( (manifest: Manifest[T], state: ResponseState) ) =>
|
||||||
|
entityUnmarshaller(manifest)(response.entity) match {
|
||||||
|
case Right(value) ⇒
|
||||||
|
state match {
|
||||||
|
case ResponseState.Success =>
|
||||||
|
ApiResponse(response.status.intValue, value, response.headers.map(header => (header.name, header.value)).toMap)
|
||||||
|
case ResponseState.Error =>
|
||||||
|
throw new ApiError(response.status.intValue, "Error response received",
|
||||||
|
Some(value),
|
||||||
|
headers = response.headers.map(header => (header.name, header.value)).toMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
case Left(MalformedContent(error, Some(cause))) ⇒
|
||||||
|
throw new ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), cause)
|
||||||
|
|
||||||
|
case Left(MalformedContent(error, None)) ⇒
|
||||||
|
throw new ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString))
|
||||||
|
|
||||||
|
case Left(ContentExpected) ⇒
|
||||||
|
throw new ApiError(response.status.intValue, s"Unable to unmarshall empty response to [$manifest]", Some(response.entity.toString))
|
||||||
|
}
|
||||||
|
|
||||||
|
case _ => throw new ApiError(response.status.intValue, "Unexpected response code", Some(response.entity.toString))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def entityUnmarshaller[T](implicit mf: Manifest[T]): Unmarshaller[T] =
|
||||||
|
Unmarshaller[T](MediaTypes.`application/json`) {
|
||||||
|
case x: HttpEntity.NonEmpty ⇒
|
||||||
|
parse(x.asString(defaultCharset = HttpCharsets.`UTF-8`))
|
||||||
|
.noNulls
|
||||||
|
.camelizeKeys
|
||||||
|
.extract[T]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed trait CustomContentTypes {
|
||||||
|
|
||||||
|
def normalizedContentType(original: String): ContentType =
|
||||||
|
MediaTypes.forExtension(original) map (ContentType(_)) getOrElse parseContentType(original)
|
||||||
|
|
||||||
|
def parseContentType(contentType: String): ContentType = {
|
||||||
|
val contentTypeAsRawHeader = HttpHeaders.RawHeader("Content-Type", contentType)
|
||||||
|
val parsedContentTypeHeader = HttpParser.parseHeader(contentTypeAsRawHeader)
|
||||||
|
(parsedContentTypeHeader: @unchecked) match {
|
||||||
|
case Right(ct: HttpHeaders.`Content-Type`) =>
|
||||||
|
ct.contentType
|
||||||
|
case Left(error: ErrorInfo) =>
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
s"Error converting '$contentType' to a ContentType header: '${error.summary}'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed trait UntrustedSslContext {
|
||||||
|
this: ApiInvoker =>
|
||||||
|
|
||||||
|
implicit lazy val trustfulSslContext: SSLContext = {
|
||||||
|
settings.alwaysTrustCertificates match {
|
||||||
|
case false =>
|
||||||
|
SSLContext.getDefault
|
||||||
|
|
||||||
|
case true =>
|
||||||
|
class IgnoreX509TrustManager extends X509TrustManager {
|
||||||
|
def checkClientTrusted(chain: Array[X509Certificate], authType: String): Unit = {}
|
||||||
|
|
||||||
|
def checkServerTrusted(chain: Array[X509Certificate], authType: String): Unit = {}
|
||||||
|
|
||||||
|
def getAcceptedIssuers = null
|
||||||
|
}
|
||||||
|
|
||||||
|
val context = SSLContext.getInstance("TLS")
|
||||||
|
context.init(null, Array(new IgnoreX509TrustManager), null)
|
||||||
|
context
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
implicit val clientSSLEngineProvider =
|
||||||
|
ClientSSLEngineProvider {
|
||||||
|
_ =>
|
||||||
|
val engine = trustfulSslContext.createSSLEngine()
|
||||||
|
engine.setUseClientMode(true)
|
||||||
|
engine
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package {{invokerPackage}}
|
||||||
|
|
||||||
|
sealed trait ResponseState
|
||||||
|
object ResponseState {
|
||||||
|
case object Success extends ResponseState
|
||||||
|
case object Error extends ResponseState
|
||||||
|
}
|
||||||
|
|
||||||
|
case class ApiRequest[U](
|
||||||
|
// required fields
|
||||||
|
method: ApiMethod,
|
||||||
|
basePath: String,
|
||||||
|
operationPath: String,
|
||||||
|
contentType: String,
|
||||||
|
|
||||||
|
// optional fields
|
||||||
|
responses: Map[Int, (Manifest[_], ResponseState)] = Map.empty,
|
||||||
|
bodyParam: Option[Any] = None,
|
||||||
|
formParams: Map[String, Any] = Map.empty,
|
||||||
|
pathParams: Map[String, Any] = Map.empty,
|
||||||
|
queryParams: Map[String, Any] = Map.empty,
|
||||||
|
headerParams: Map[String, Any] = Map.empty,
|
||||||
|
credentials: Seq[Credentials] = List.empty) {
|
||||||
|
|
||||||
|
def withCredentials(cred: Credentials) = copy[U](credentials = credentials :+ cred)
|
||||||
|
|
||||||
|
def withApiKey(key: ApiKeyValue, keyName: String, location: ApiKeyLocation) = withCredentials(ApiKeyCredentials(key, keyName, location))
|
||||||
|
|
||||||
|
def withSuccessResponse[T](code: Int)(implicit m: Manifest[T]) = copy[U](responses = responses + (code -> (m, ResponseState.Success)))
|
||||||
|
|
||||||
|
def withErrorResponse[T](code: Int)(implicit m: Manifest[T]) = copy[U](responses = responses + (code -> (m, ResponseState.Error)))
|
||||||
|
|
||||||
|
def withDefaultSuccessResponse[T](implicit m: Manifest[T]) = withSuccessResponse[T](0)
|
||||||
|
|
||||||
|
def withDefaultErrorResponse[T](implicit m: Manifest[T]) = withErrorResponse[T](0)
|
||||||
|
|
||||||
|
def responseForCode(statusCode: Int): Option[(Manifest[_], ResponseState)] = responses.get(statusCode) orElse responses.get(0)
|
||||||
|
|
||||||
|
def withoutBody() = copy[U](bodyParam = None)
|
||||||
|
|
||||||
|
def withBody(body: Any) = copy[U](bodyParam = Some(body))
|
||||||
|
|
||||||
|
def withFormParam(name: String, value: Any) = copy[U](formParams = formParams + (name -> value))
|
||||||
|
|
||||||
|
def withPathParam(name: String, value: Any) = copy[U](pathParams = pathParams + (name -> value))
|
||||||
|
|
||||||
|
def withQueryParam(name: String, value: Any) = copy[U](queryParams = queryParams + (name -> value))
|
||||||
|
|
||||||
|
def withHeaderParam(name: String, value: Any) = copy[U](headerParams = headerParams + (name -> value))
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package {{invokerPackage}}
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
import akka.actor.{ExtendedActorSystem, Extension, ExtensionKey}
|
||||||
|
import com.typesafe.config.Config
|
||||||
|
import io.swagger.client.core.ApiInvoker.CustomStatusCode
|
||||||
|
import spray.http.HttpHeaders.RawHeader
|
||||||
|
|
||||||
|
import scala.collection.JavaConversions._
|
||||||
|
import scala.concurrent.duration.FiniteDuration
|
||||||
|
|
||||||
|
class ApiSettings(config: Config) extends Extension {
|
||||||
|
def this(system: ExtendedActorSystem) = this(system.settings.config)
|
||||||
|
|
||||||
|
private def cfg = config.getConfig("io.swagger.client.apiRequest")
|
||||||
|
|
||||||
|
val alwaysTrustCertificates = cfg.getBoolean("trust-certificates")
|
||||||
|
val defaultHeaders = cfg.getConfig("default-headers").entrySet.toList.map(c => RawHeader(c.getKey, c.getValue.render))
|
||||||
|
val connectionTimeout = FiniteDuration(cfg.getDuration("connection-timeout", TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS)
|
||||||
|
val compressionEnabled = cfg.getBoolean("compression.enabled")
|
||||||
|
val compressionSizeThreshold = cfg.getBytes("compression.size-threshold").toInt
|
||||||
|
val customCodes = cfg.getConfigList("custom-codes").toList.map { c => CustomStatusCode(
|
||||||
|
c.getInt("code"),
|
||||||
|
c.getString("reason"),
|
||||||
|
c.getBoolean("success"))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object ApiSettings extends ExtensionKey[ApiSettings]
|
@ -0,0 +1,42 @@
|
|||||||
|
package {{apiPackage}}
|
||||||
|
|
||||||
|
import {{modelPackage}}._
|
||||||
|
import org.json4s._
|
||||||
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
|
object EnumsSerializers {
|
||||||
|
|
||||||
|
def all = Seq[Serializer[_]](){{#models}}{{#model}}{{#hasEnums}}{{#vars}}{{#isEnum}} :+
|
||||||
|
new EnumNameSerializer({{classname}}Enums.{{datatypeWithEnum}}){{/isEnum}}{{/vars}}{{/hasEnums}}{{/model}}{{/models}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private class EnumNameSerializer[E <: Enumeration: ClassTag](enum: E)
|
||||||
|
extends Serializer[E#Value] {
|
||||||
|
import JsonDSL._
|
||||||
|
|
||||||
|
val EnumerationClass = classOf[E#Value]
|
||||||
|
|
||||||
|
def deserialize(implicit format: Formats):
|
||||||
|
PartialFunction[(TypeInfo, JValue), E#Value] = {
|
||||||
|
case (t @ TypeInfo(EnumerationClass, _), json) if isValid(json) => {
|
||||||
|
json match {
|
||||||
|
case JString(value) =>
|
||||||
|
enum.withName(value)
|
||||||
|
case value =>
|
||||||
|
throw new MappingException(s"Can't convert $value to $EnumerationClass")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private[this] def isValid(json: JValue) = json match {
|
||||||
|
case JString(value) if enum.values.exists(_.toString == value) => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
|
||||||
|
case i: E#Value => i.toString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
{{^notes.isEmpty}}
|
||||||
|
{{notes}}
|
||||||
|
{{/notes.isEmpty}}
|
||||||
|
|
||||||
|
Expected answers:
|
||||||
|
{{#responses}}
|
||||||
|
code {{code}} : {{dataType}} {{^message.isEmpty}}({{message}}){{/message.isEmpty}}{{^headers.isEmpty}}
|
||||||
|
Headers :{{#headers}}
|
||||||
|
{{baseName}} - {{description}}{{/headers}}{{/headers.isEmpty}}
|
||||||
|
{{/responses}}
|
||||||
|
{{#authMethods.0}}
|
||||||
|
|
||||||
|
Available security schemes:
|
||||||
|
{{#authMethods}}
|
||||||
|
{{name}} ({{type}})
|
||||||
|
{{/authMethods}}
|
||||||
|
{{/authMethods.0}}
|
||||||
|
|
||||||
|
{{#allParams}}
|
||||||
|
@param {{paramName}} {{description}}
|
||||||
|
{{/allParams}}
|
@ -0,0 +1 @@
|
|||||||
|
{{#allParams}}{{paramName}}: {{#required}}{{dataType}}{{/required}}{{^required}}{{#isContainer}}{{dataType}}{{/isContainer}}{{^isContainer}}Option[{{dataType}}]{{/isContainer}}{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{^required}}{{^isContainer}} = None{{/isContainer}}{{/required}}{{/defaultValue}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#authMethods.0}})(implicit {{#authMethods}}{{#isApiKey}}apiKey: ApiKeyValue{{/isApiKey}}{{#isBasic}}basicAuth: BasicCredentials{{/isBasic}}{{#hasMore}}, {{/hasMore}}{{/authMethods}}{{/authMethods.0}}
|
@ -0,0 +1,30 @@
|
|||||||
|
package {{package}}
|
||||||
|
|
||||||
|
import {{invokerPackage}}.ApiModel
|
||||||
|
import org.joda.time.DateTime
|
||||||
|
|
||||||
|
{{#models}}
|
||||||
|
{{#model}}
|
||||||
|
|
||||||
|
case class {{classname}} (
|
||||||
|
{{#vars}}{{#description}}/* {{{description}}} */
|
||||||
|
{{/description}}{{name}}: {{^required}}Option[{{/required}}{{^isEnum}}{{datatype}}{{/isEnum}}{{#isEnum}}{{classname}}Enums.{{datatypeWithEnum}}{{/isEnum}}{{^required}}]{{/required}}{{#hasMore}},{{/hasMore}}{{^hasMore}}){{/hasMore}}
|
||||||
|
{{/vars}} extends ApiModel
|
||||||
|
|
||||||
|
{{#hasEnums}}
|
||||||
|
object {{classname}}Enums {
|
||||||
|
|
||||||
|
{{#vars}}{{#isEnum}}type {{datatypeWithEnum}} = {{datatypeWithEnum}}.Value
|
||||||
|
{{/isEnum}}{{/vars}}
|
||||||
|
{{#vars}}{{#isEnum}}object {{datatypeWithEnum}} extends Enumeration {
|
||||||
|
{{#_enum}}
|
||||||
|
val {{#fnEnumEntry}}{{.}}{{/fnEnumEntry}} = Value("{{.}}")
|
||||||
|
{{/_enum}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/isEnum}}{{/vars}}
|
||||||
|
}
|
||||||
|
{{/hasEnums}}
|
||||||
|
{{/model}}
|
||||||
|
{{/models}}
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
{{#onlyOneSuccess}}{{^defaultResponse}}Unit{{/defaultResponse}}{{#defaultResponse}}{{#responses}}{{#isDefault}}{{#dataType}}{{dataType}}{{/dataType}}{{^dataType}}Unit{{/dataType}}{{/isDefault}}{{/responses}}{{/defaultResponse}}{{/onlyOneSuccess}}{{^onlyOneSuccess}}{{#responses}}{{#-first}}{{^hasMore}}{{#dataType}}{{dataType}}{{/dataType}}{{^dataType}}Unit{{/dataType}}{{/hasMore}}{{#hasMore}}Any{{/hasMore}}{{/-first}}{{/responses}}{{/onlyOneSuccess}}
|
@ -0,0 +1 @@
|
|||||||
|
"{{baseName}}", {{#isContainer}}ArrayValues({{paramName}}{{#collectionFormat}}, {{collectionFormat.toUpperCase}}{{/collectionFormat}}){{/isContainer}}{{^isContainer}}{{paramName}}{{/isContainer}}
|
@ -0,0 +1,227 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>{{groupId}}</groupId>
|
||||||
|
<artifactId>{{artifactId}}</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>{{artifactId}}</name>
|
||||||
|
<version>{{artifactVersion}}</version>
|
||||||
|
<prerequisites>
|
||||||
|
<maven>2.2.0</maven>
|
||||||
|
</prerequisites>
|
||||||
|
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>maven-mongodb-plugin-repo</id>
|
||||||
|
<name>maven mongodb plugin repository</name>
|
||||||
|
<url>http://maven-mongodb-plugin.googlecode.com/svn/maven/repo</url>
|
||||||
|
<layout>default</layout>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.12</version>
|
||||||
|
<configuration>
|
||||||
|
<systemProperties>
|
||||||
|
<property>
|
||||||
|
<name>loggerPath</name>
|
||||||
|
<value>conf/log4j.properties</value>
|
||||||
|
</property>
|
||||||
|
</systemProperties>
|
||||||
|
<argLine>-Xms512m -Xmx1500m</argLine>
|
||||||
|
<parallel>methods</parallel>
|
||||||
|
<forkMode>pertest</forkMode>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/lib</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- attach test jar -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
<goal>test-jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>build-helper-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>add_sources</id>
|
||||||
|
<phase>generate-sources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-source</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<sources>
|
||||||
|
<source>
|
||||||
|
src/main/java</source>
|
||||||
|
</sources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>add_test_sources</id>
|
||||||
|
<phase>generate-test-sources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-test-source</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<sources>
|
||||||
|
<source>
|
||||||
|
src/test/java</source>
|
||||||
|
</sources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>2.3.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>
|
||||||
|
1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.alchim31.maven</groupId>
|
||||||
|
<artifactId>scala-maven-plugin</artifactId>
|
||||||
|
<version>${scala-maven-plugin-version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>scala-compile-first</id>
|
||||||
|
<phase>process-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-source</goal>
|
||||||
|
<goal>compile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>scala-test-compile</id>
|
||||||
|
<phase>process-test-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<args>
|
||||||
|
<arg>-feature</arg>
|
||||||
|
</args>
|
||||||
|
<jvmArgs>
|
||||||
|
<jvmArg>-Xms128m</jvmArg>
|
||||||
|
<jvmArg>-Xmx1500m</jvmArg>
|
||||||
|
</jvmArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<reporting>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.scala-tools</groupId>
|
||||||
|
<artifactId>maven-scala-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<scalaVersion>${scala-version}</scalaVersion>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</reporting>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.scala-lang</groupId>
|
||||||
|
<artifactId>scala-library</artifactId>
|
||||||
|
<version>${scala-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.wordnik</groupId>
|
||||||
|
<artifactId>swagger-core</artifactId>
|
||||||
|
<version>${swagger-core-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.scalatest</groupId>
|
||||||
|
<artifactId>scalatest_2.10</artifactId>
|
||||||
|
<version>${scala-test-version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>${junit-version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>joda-time</groupId>
|
||||||
|
<artifactId>joda-time</artifactId>
|
||||||
|
<version>${joda-time-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.joda</groupId>
|
||||||
|
<artifactId>joda-convert</artifactId>
|
||||||
|
<version>${joda-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.typesafe</groupId>
|
||||||
|
<artifactId>config</artifactId>
|
||||||
|
<version>1.2.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.typesafe.akka</groupId>
|
||||||
|
<artifactId>akka-actor_2.10</artifactId>
|
||||||
|
<version>${akka-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.spray</groupId>
|
||||||
|
<artifactId>spray-client</artifactId>
|
||||||
|
<version>${spray-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.json4s</groupId>
|
||||||
|
<artifactId>json4s-jackson_2.10</artifactId>
|
||||||
|
<version>${json4s-jackson-version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<properties>
|
||||||
|
<scala-version>2.10.4</scala-version>
|
||||||
|
<json4s-jackson-version>3.2.11</json4s-jackson-version>
|
||||||
|
<json4s-ext-version>3.2.11</json4s-ext-version>
|
||||||
|
<spray-version>1.3.1</spray-version>
|
||||||
|
<akka-version>2.3.9</akka-version>
|
||||||
|
<joda-version>1.2</joda-version>
|
||||||
|
<joda-time-version>2.2</joda-time-version>
|
||||||
|
<swagger-core-version>1.5.0-M1</swagger-core-version>
|
||||||
|
<maven-plugin.version>1.0.0</maven-plugin.version>
|
||||||
|
|
||||||
|
<junit-version>4.8.1</junit-version>
|
||||||
|
<scala-maven-plugin-version>3.1.5</scala-maven-plugin-version>
|
||||||
|
<scala-test-version>2.1.3</scala-test-version>
|
||||||
|
</properties>
|
||||||
|
</project>
|
@ -0,0 +1,24 @@
|
|||||||
|
{{configKeyPath}} {
|
||||||
|
|
||||||
|
{{configKey}} {
|
||||||
|
|
||||||
|
compression {
|
||||||
|
enabled: false
|
||||||
|
size-threshold: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
trust-certificates: true
|
||||||
|
|
||||||
|
connection-timeout: {{defaultTimeout}}ms
|
||||||
|
|
||||||
|
default-headers {
|
||||||
|
"userAgent": "{{artifactId}}_{{artifactVersion}}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// let you define custom http status code, as in :
|
||||||
|
// { code: 601, reason: "some custom http status code", success: false }
|
||||||
|
custom-codes : []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spray.can.host-connector.max-redirects = 10
|
@ -0,0 +1,166 @@
|
|||||||
|
package {{invokerPackage}}
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URLEncoder
|
||||||
|
import scala.util.Try
|
||||||
|
|
||||||
|
sealed trait ApiReturnWithHeaders {
|
||||||
|
def headers: Map[String, String]
|
||||||
|
def header(name: String): Option[String] = headers.get(name)
|
||||||
|
def getStringHeader(name: String) = header(name)
|
||||||
|
def getIntHeader(name: String) = castedHeader(name, java.lang.Integer.parseInt)
|
||||||
|
def getLongHeader(name: String) = castedHeader(name, java.lang.Long.parseLong)
|
||||||
|
def getFloatHeader(name: String) = castedHeader(name, java.lang.Float.parseFloat)
|
||||||
|
def getDoubleHeader(name: String) = castedHeader(name, java.lang.Double.parseDouble)
|
||||||
|
def getBooleanHeader(name: String) = castedHeader(name, java.lang.Boolean.parseBoolean)
|
||||||
|
private def castedHeader[U](name: String, conversion: String => U): Option[U] = { Try { header(name).map( conversion ) }.get }
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed case class ApiResponse[T](code: Int, content: T, headers: Map[String, String] = Map.empty)
|
||||||
|
extends ApiReturnWithHeaders
|
||||||
|
|
||||||
|
sealed case class ApiError[T](code: Int, message: String, responseContent: Option[T], cause: Throwable = null, headers: Map[String, String] = Map.empty)
|
||||||
|
extends Throwable(s"($code) $message.${responseContent.map(s => s" Content : $s").getOrElse("")}", cause)
|
||||||
|
with ApiReturnWithHeaders
|
||||||
|
|
||||||
|
sealed case class ApiMethod(value: String)
|
||||||
|
|
||||||
|
object ApiMethods {
|
||||||
|
val CONNECT = ApiMethod("CONNECT")
|
||||||
|
val DELETE = ApiMethod("DELETE")
|
||||||
|
val GET = ApiMethod("GET")
|
||||||
|
val HEAD = ApiMethod("HEAD")
|
||||||
|
val OPTIONS = ApiMethod("OPTIONS")
|
||||||
|
val PATCH = ApiMethod("PATCH")
|
||||||
|
val POST = ApiMethod("POST")
|
||||||
|
val PUT = ApiMethod("PUT")
|
||||||
|
val TRACE = ApiMethod("TRACE")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This trait needs to be added to any model defined by the api.
|
||||||
|
*/
|
||||||
|
trait ApiModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single trait defining a credential that can be transformed to a paramName / paramValue tupple
|
||||||
|
*/
|
||||||
|
sealed trait Credentials {
|
||||||
|
def asQueryParam: Option[(String, String)] = None
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed case class BasicCredentials(user: String, password: String) extends Credentials
|
||||||
|
|
||||||
|
sealed case class ApiKeyCredentials(key: ApiKeyValue, keyName: String, location: ApiKeyLocation) extends Credentials {
|
||||||
|
override def asQueryParam: Option[(String, String)] = location match {
|
||||||
|
case ApiKeyLocations.QUERY => Some((keyName, key.value))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed case class ApiKeyValue(value: String)
|
||||||
|
|
||||||
|
sealed trait ApiKeyLocation
|
||||||
|
|
||||||
|
object ApiKeyLocations {
|
||||||
|
|
||||||
|
case object QUERY extends ApiKeyLocation
|
||||||
|
|
||||||
|
case object HEADER extends ApiKeyLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Case class used to unapply numeric values only in pattern matching
|
||||||
|
* @param value the string representation of the numeric value
|
||||||
|
*/
|
||||||
|
sealed case class NumericValue(value: String) {
|
||||||
|
override def toString = value
|
||||||
|
}
|
||||||
|
|
||||||
|
object NumericValue {
|
||||||
|
def unapply(n: Any): Option[NumericValue] = n match {
|
||||||
|
case (_: Int | _: Long | _: Float | _: Double | _: Boolean | _: Byte) => Some(NumericValue(String.valueOf(n)))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for params being arrays
|
||||||
|
*/
|
||||||
|
sealed case class ArrayValues(values: Seq[Any], format: CollectionFormat = CollectionFormats.CSV)
|
||||||
|
|
||||||
|
object ArrayValues {
|
||||||
|
def apply(values: Option[Seq[Any]], format: CollectionFormat): ArrayValues =
|
||||||
|
ArrayValues(values.getOrElse(Seq.empty), format)
|
||||||
|
|
||||||
|
def apply(values: Option[Seq[Any]]): ArrayValues = ArrayValues(values, CollectionFormats.CSV)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines how arrays should be rendered in query strings.
|
||||||
|
*/
|
||||||
|
sealed trait CollectionFormat
|
||||||
|
|
||||||
|
trait MergedArrayFormat extends CollectionFormat {
|
||||||
|
def separator: String
|
||||||
|
}
|
||||||
|
|
||||||
|
object CollectionFormats {
|
||||||
|
|
||||||
|
case object CSV extends MergedArrayFormat {
|
||||||
|
override val separator = ","
|
||||||
|
}
|
||||||
|
|
||||||
|
case object TSV extends MergedArrayFormat {
|
||||||
|
override val separator = "\t"
|
||||||
|
}
|
||||||
|
|
||||||
|
case object SSV extends MergedArrayFormat {
|
||||||
|
override val separator = " "
|
||||||
|
}
|
||||||
|
|
||||||
|
case object PIPES extends MergedArrayFormat {
|
||||||
|
override val separator = "|"
|
||||||
|
}
|
||||||
|
|
||||||
|
case object MULTI extends CollectionFormat
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object ParametersMap {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pimp parameters maps (Map[String, Any]) in order to transform them in a sequence of String -> Any tupples,
|
||||||
|
* with valid url-encoding, arrays handling, files preservation, ...
|
||||||
|
*/
|
||||||
|
implicit class ParametersMapImprovements(val m: Map[String, Any]) {
|
||||||
|
|
||||||
|
def asFormattedParamsList = m.toList.flatMap(formattedParams)
|
||||||
|
|
||||||
|
def asFormattedParams = m.flatMap(formattedParams)
|
||||||
|
|
||||||
|
private def urlEncode(v: Any) = URLEncoder.encode(String.valueOf(v), "utf-8").replaceAll("\\+", "%20")
|
||||||
|
|
||||||
|
private def formattedParams(tuple: (String, Any)): Seq[(String, Any)] = formattedParams(tuple._1, tuple._2)
|
||||||
|
|
||||||
|
private def formattedParams(name: String, value: Any): Seq[(String, Any)] = value match {
|
||||||
|
case arr: ArrayValues =>
|
||||||
|
arr.format match {
|
||||||
|
case CollectionFormats.MULTI => arr.values.flatMap(formattedParams(name, _))
|
||||||
|
case format: MergedArrayFormat => Seq((name, arr.values.mkString(format.separator)))
|
||||||
|
}
|
||||||
|
case None => Seq.empty
|
||||||
|
case Some(opt) =>
|
||||||
|
formattedParams(name, opt)
|
||||||
|
case s: Seq[Any] =>
|
||||||
|
formattedParams(name, ArrayValues(s))
|
||||||
|
case v: String => Seq((name, urlEncode(v)))
|
||||||
|
case NumericValue(v) => Seq((name, urlEncode(v)))
|
||||||
|
case f: File => Seq((name, f))
|
||||||
|
case m: ApiModel => Seq((name, m))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
{{#onlyOneSuccess}}{{#isDefault}}Success{{/isDefault}}{{^isDefault}}Error{{/isDefault}}{{/onlyOneSuccess}}{{^onlyOneSuccess}}Success{{/onlyOneSuccess}}
|
@ -1,9 +1,17 @@
|
|||||||
|
{{#useAndroidMavenGradlePlugin}}
|
||||||
|
group = '{{groupId}}'
|
||||||
|
project.version = '{{artifactVersion}}'
|
||||||
|
{{/useAndroidMavenGradlePlugin}}
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:1.2.2'
|
classpath 'com.android.tools.build:gradle:1.2.2'
|
||||||
|
{{#useAndroidMavenGradlePlugin}}
|
||||||
|
classpath 'com.github.dcendents:android-maven-plugin:1.2'
|
||||||
|
{{/useAndroidMavenGradlePlugin}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,7 +21,11 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
|
{{#useAndroidMavenGradlePlugin}}
|
||||||
|
apply plugin: 'com.github.dcendents.android-maven'
|
||||||
|
{{/useAndroidMavenGradlePlugin}}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 22
|
compileSdkVersion 22
|
||||||
@ -22,6 +34,17 @@ android {
|
|||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 22
|
targetSdkVersion 22
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +60,12 @@ dependencies {
|
|||||||
compile "com.google.code.gson:gson:$gson_version"
|
compile "com.google.code.gson:gson:$gson_version"
|
||||||
compile "org.apache.httpcomponents:httpcore:$httpclient_version"
|
compile "org.apache.httpcomponents:httpcore:$httpclient_version"
|
||||||
compile "org.apache.httpcomponents:httpclient:$httpclient_version"
|
compile "org.apache.httpcomponents:httpclient:$httpclient_version"
|
||||||
compile "org.apache.httpcomponents:httpmime:$httpclient_version"
|
compile ("org.apache.httpcomponents:httpcore:$httpcore_version") {
|
||||||
|
exclude(group: 'org.apache.httpcomponents', module: 'httpclient')
|
||||||
|
}
|
||||||
|
compile ("org.apache.httpcomponents:httpmime:$httpmime_version") {
|
||||||
|
exclude(group: 'org.apache.httpcomponents', module: 'httpclient')
|
||||||
|
}
|
||||||
testCompile "junit:junit:$junit_version"
|
testCompile "junit:junit:$junit_version"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +76,18 @@ afterEvaluate {
|
|||||||
task.dependsOn variant.javaCompile
|
task.dependsOn variant.javaCompile
|
||||||
task.from variant.javaCompile.destinationDir
|
task.from variant.javaCompile.destinationDir
|
||||||
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
|
task.destinationDir = project.file("${project.buildDir}/outputs/jar")
|
||||||
task.archiveName = "${project.name}-${variant.baseName}.jar"
|
task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
|
||||||
artifacts.add('archives', task);
|
artifacts.add('archives', task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{{#useAndroidMavenGradlePlugin}}
|
||||||
|
task sourcesJar(type: Jar) {
|
||||||
|
from android.sourceSets.main.java.srcDirs
|
||||||
|
classifier = 'sources'
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives sourcesJar
|
||||||
|
}
|
||||||
|
{{/useAndroidMavenGradlePlugin}}
|
@ -0,0 +1 @@
|
|||||||
|
rootProject.name = "{{artifactId}}"
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using RestSharp;
|
||||||
using {{invokerPackage}};
|
using {{invokerPackage}};
|
||||||
using {{modelPackage}};
|
using {{modelPackage}};
|
||||||
{{#imports}}
|
{{#imports}}
|
||||||
@ -9,101 +10,73 @@ namespace {{package}} {
|
|||||||
{{#operations}}
|
{{#operations}}
|
||||||
public class {{classname}} {
|
public class {{classname}} {
|
||||||
string basePath;
|
string basePath;
|
||||||
private readonly ApiInvoker apiInvoker = ApiInvoker.GetInstance();
|
protected RestClient restClient;
|
||||||
|
|
||||||
public {{classname}}(String basePath = "{{basePath}}")
|
public {{classname}}(String basePath = "{{basePath}}")
|
||||||
{
|
{
|
||||||
this.basePath = basePath;
|
this.basePath = basePath;
|
||||||
|
this.restClient = new RestClient(basePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiInvoker getInvoker() {
|
/// <summary>
|
||||||
return apiInvoker;
|
/// Sets the endpoint base url for the services being accessed
|
||||||
}
|
/// </summary>
|
||||||
|
/// <param name="basePath"> Base URL
|
||||||
// Sets the endpoint base url for the services being accessed
|
/// <returns></returns>
|
||||||
public void setBasePath(string basePath) {
|
public void SetBasePath(string basePath) {
|
||||||
this.basePath = basePath;
|
this.basePath = basePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the endpoint base url for the services being accessed
|
/// <summary>
|
||||||
public String getBasePath() {
|
/// Gets the endpoint base url for the services being accessed
|
||||||
return basePath;
|
/// <returns>Base URL</returns>
|
||||||
|
/// </summary>
|
||||||
|
public String GetBasePath() {
|
||||||
|
return this.basePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
{{#operation}}
|
{{#operation}}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// {{summary}} {{notes}}
|
/// {{summary}} {{notes}}
|
||||||
/// </summary>
|
/// </summary>
|
||||||
{{#allParams}}/// <param name="{{paramName}}">{{description}}</param>
|
{{#allParams}} /// <param name="{{paramName}}">{{description}}</param>
|
||||||
{{#hasMore}} {{/hasMore}}{{/allParams}}
|
{{/allParams}}
|
||||||
/// <returns></returns>
|
/// <returns>{{#returnType}}{{{returnType}}}{{/returnType}}</returns>
|
||||||
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {
|
public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {
|
||||||
// create path and map variables
|
|
||||||
var path = "{{path}}".Replace("{format}","json"){{#pathParams}}.Replace("{" + "{{baseName}}" + "}", apiInvoker.ParameterToString({{{paramName}}})){{/pathParams}};
|
|
||||||
|
|
||||||
// query params
|
var _request = new RestRequest("{{path}}", Method.{{httpMethod}});
|
||||||
var queryParams = new Dictionary<String, String>();
|
|
||||||
var headerParams = new Dictionary<String, String>();
|
|
||||||
var formParams = new Dictionary<String, object>();
|
|
||||||
|
|
||||||
{{#requiredParamCount}}
|
{{#allParams}}{{#required}}
|
||||||
// verify required params are set
|
// verify the required parameter '{{paramName}}' is set
|
||||||
if ({{/requiredParamCount}}{{#requiredParams}} {{paramName}} == null {{#hasMore}}|| {{/hasMore}}{{/requiredParams}}{{#requiredParamCount}}) {
|
if ({{paramName}} == null) throw new ApiException(400, "Missing required parameter '{{paramName}}' when calling {{nickname}}");
|
||||||
throw new ApiException(400, "missing required params");
|
{{/required}}{{/allParams}}
|
||||||
|
|
||||||
|
// add default header, if any
|
||||||
|
foreach(KeyValuePair<string, string> defaultHeader in ApiInvoker.GetDefaultHeader())
|
||||||
|
{
|
||||||
|
_request.AddHeader(defaultHeader.Key, defaultHeader.Value);
|
||||||
}
|
}
|
||||||
{{/requiredParamCount}}
|
|
||||||
|
|
||||||
{{#queryParams}}if ({{paramName}} != null){
|
_request.AddUrlSegment("format", "json"); // set format to json by default
|
||||||
queryParams.Add("{{baseName}}", apiInvoker.ParameterToString({{paramName}}));
|
{{#pathParams}}_request.AddUrlSegment("{{baseName}}", ApiInvoker.ParameterToString({{{paramName}}})); // path (url segment) parameter
|
||||||
}
|
{{/pathParams}}
|
||||||
|
{{#queryParams}} if ({{paramName}} != null) _request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // query parameter
|
||||||
{{/queryParams}}
|
{{/queryParams}}
|
||||||
|
{{#headerParams}} if ({{paramName}} != null) _request.AddHeader("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // header parameter
|
||||||
{{#headerParams}}headerParams.Add("{{baseName}}", apiInvoker.ParameterToString({{paramName}}));
|
|
||||||
{{/headerParams}}
|
{{/headerParams}}
|
||||||
|
{{#formParams}}if ({{paramName}} != null) {{#isFile}}_request.AddFile("{{baseName}}", {{paramName}});{{/isFile}}{{^isFile}}_request.AddParameter("{{baseName}}", ApiInvoker.ParameterToString({{paramName}})); // form parameter{{/isFile}}
|
||||||
{{#formParams}}if ({{paramName}} != null){
|
|
||||||
if({{paramName}} is byte[]) {
|
|
||||||
formParams.Add("{{baseName}}", {{paramName}});
|
|
||||||
} else {
|
|
||||||
formParams.Add("{{baseName}}", apiInvoker.ParameterToString({{paramName}}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{{/formParams}}
|
{{/formParams}}
|
||||||
|
{{#bodyParam}}_request.AddParameter("application/json", ApiInvoker.Serialize({{paramName}}), ParameterType.RequestBody); // http body (model) parameter
|
||||||
|
{{/bodyParam}}
|
||||||
|
|
||||||
try {
|
// make the HTTP request
|
||||||
if (typeof({{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}) == typeof(byte[])) {
|
IRestResponse response = restClient.Execute(_request);
|
||||||
{{#returnType}}
|
if (((int)response.StatusCode) >= 400) {
|
||||||
var response = apiInvoker.invokeBinaryAPI(basePath, path, "GET", queryParams, null, headerParams, formParams);
|
throw new ApiException ((int)response.StatusCode, "Error calling {{nickname}}: " + response.Content);
|
||||||
return ((object)response) as {{{returnType}}};
|
|
||||||
{{/returnType}}
|
|
||||||
{{^returnType}}
|
|
||||||
apiInvoker.invokeBinaryAPI(basePath, path, "GET", queryParams, null, headerParams, formParams);
|
|
||||||
return;
|
|
||||||
{{/returnType}}
|
|
||||||
} else {
|
|
||||||
{{#returnType}}
|
|
||||||
var response = apiInvoker.invokeAPI(basePath, path, "{{httpMethod}}", queryParams, {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}, headerParams, formParams);
|
|
||||||
if (response != null){
|
|
||||||
return ({{{returnType}}}) ApiInvoker.deserialize(response, typeof({{{returnType}}}));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
{{/returnType}}
|
|
||||||
{{^returnType}}
|
|
||||||
apiInvoker.invokeAPI(basePath, path, "{{httpMethod}}", queryParams, {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}, headerParams, formParams);
|
|
||||||
return;
|
|
||||||
{{/returnType}}
|
|
||||||
}
|
|
||||||
} catch (ApiException ex) {
|
|
||||||
if(ex.ErrorCode == 404) {
|
|
||||||
return {{#returnType}}null{{/returnType}};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
{{#returnType}}return ({{{returnType}}}) ApiInvoker.Deserialize(response.Content, typeof({{{returnType}}}));{{/returnType}}{{^returnType}}
|
||||||
|
return;{{/returnType}}
|
||||||
}
|
}
|
||||||
{{/operation}}
|
{{/operation}}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace {{invokerPackage}} {
|
namespace {{invokerPackage}} {
|
||||||
|
|
||||||
public class ApiException : Exception {
|
public class ApiException : Exception {
|
||||||
|
|
||||||
private int errorCode = 0;
|
public int ErrorCode { get; set; }
|
||||||
|
|
||||||
public ApiException() {}
|
public ApiException() {}
|
||||||
|
|
||||||
public int ErrorCode {
|
public ApiException(int errorCode, string message) : base(message) {
|
||||||
get
|
this.ErrorCode = errorCode;
|
||||||
{
|
|
||||||
return errorCode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiException(int errorCode, string message) : base(message) {
|
|
||||||
this.errorCode = errorCode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
@ -1,235 +1,81 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace {{invokerPackage}} {
|
namespace {{invokerPackage}} {
|
||||||
public class ApiInvoker {
|
public class ApiInvoker {
|
||||||
private static readonly ApiInvoker _instance = new ApiInvoker();
|
private static Dictionary<String, String> defaultHeaderMap = new Dictionary<String, String>();
|
||||||
private Dictionary<String, String> defaultHeaderMap = new Dictionary<String, String>();
|
|
||||||
|
|
||||||
public static ApiInvoker GetInstance() {
|
/// <summary>
|
||||||
return _instance;
|
/// Add default header
|
||||||
}
|
/// </summary>
|
||||||
|
/// <param name="key"> Header field name
|
||||||
|
/// <param name="value"> Header field value
|
||||||
|
/// <returns></returns>
|
||||||
|
public static void AddDefaultHeader(string key, string value) {
|
||||||
|
defaultHeaderMap.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add default header
|
/// Get default header
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"> Header field name
|
/// <returns>Dictionary of default header</returns>
|
||||||
/// <param name="value"> Header field value
|
public static Dictionary<String, String> GetDefaultHeader() {
|
||||||
/// <returns></returns>
|
return defaultHeaderMap;
|
||||||
public void addDefaultHeader(string key, string value) {
|
}
|
||||||
defaultHeaderMap.Add(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// escape string (url-encoded)
|
/// escape string (url-encoded)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="str"> String to be escaped
|
/// <param name="str"> String to be escaped
|
||||||
/// <returns>Escaped string</returns>
|
/// <returns>Escaped string</returns>
|
||||||
public string escapeString(string str) {
|
public static string EscapeString(string str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// if parameter is DateTime, output in ISO8601 format, otherwise just return the string
|
/// if parameter is DateTime, output in ISO8601 format, otherwise just return the string
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj"> The parameter (header, path, query, form)
|
/// <param name="obj"> The parameter (header, path, query, form)
|
||||||
/// <returns>Formatted string</returns>
|
/// <returns>Formatted string</returns>
|
||||||
public string ParameterToString(object obj)
|
public static string ParameterToString(object obj)
|
||||||
|
{
|
||||||
|
return (obj is DateTime) ? ((DateTime)obj).ToString ("u") : Convert.ToString (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserialize the JSON string into a proper object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="json"> JSON string
|
||||||
|
/// <param name="type"> Object type
|
||||||
|
/// <returns>Object representation of the JSON string</returns>
|
||||||
|
public static object Deserialize(string json, Type type) {
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return (obj is DateTime) ? ((DateTime)obj).ToString ("u") : Convert.ToString (obj);
|
return JsonConvert.DeserializeObject(json, type);
|
||||||
}
|
}
|
||||||
|
catch (IOException e) {
|
||||||
/// <summary>
|
throw new ApiException(500, e.Message);
|
||||||
/// Deserialize the JSON string into a proper object
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="json"> JSON string
|
|
||||||
/// <param name="type"> Object type
|
|
||||||
/// <returns>Object representation of the JSON string</returns>
|
|
||||||
public static object deserialize(string json, Type type) {
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return JsonConvert.DeserializeObject(json, type);
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new ApiException(500, e.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string serialize(object obj) {
|
/// <summary>
|
||||||
try
|
/// Serialize an object into JSON string
|
||||||
{
|
/// </summary>
|
||||||
return obj != null ? JsonConvert.SerializeObject(obj) : null;
|
/// <param name="obj"> Object
|
||||||
}
|
/// <returns>JSON string</returns>
|
||||||
catch (Exception e) {
|
public static string Serialize(object obj) {
|
||||||
throw new ApiException(500, e.Message);
|
try
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string invokeAPI(string host, string path, string method, Dictionary<String, String> queryParams, object body, Dictionary<String, String> headerParams, Dictionary<String, object> formParams)
|
|
||||||
{
|
{
|
||||||
return invokeAPIInternal(host, path, method, false, queryParams, body, headerParams, formParams) as string;
|
return obj != null ? JsonConvert.SerializeObject(obj) : null;
|
||||||
}
|
}
|
||||||
|
catch (Exception e) {
|
||||||
public byte[] invokeBinaryAPI(string host, string path, string method, Dictionary<String, String> queryParams, object body, Dictionary<String, String> headerParams, Dictionary<String, object> formParams)
|
throw new ApiException(500, e.Message);
|
||||||
{
|
|
||||||
return invokeAPIInternal(host, path, method, true, queryParams, body, headerParams, formParams) as byte[];
|
|
||||||
}
|
|
||||||
|
|
||||||
private object invokeAPIInternal(string host, string path, string method, bool binaryResponse, Dictionary<String, String> queryParams, object body, Dictionary<String, String> headerParams, Dictionary<String, object> formParams) {
|
|
||||||
var b = new StringBuilder();
|
|
||||||
|
|
||||||
foreach (var queryParamItem in queryParams)
|
|
||||||
{
|
|
||||||
var value = queryParamItem.Value;
|
|
||||||
if (value == null) continue;
|
|
||||||
b.Append(b.ToString().Length == 0 ? "?" : "&");
|
|
||||||
b.Append(escapeString(queryParamItem.Key)).Append("=").Append(escapeString(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
var querystring = b.ToString();
|
|
||||||
|
|
||||||
host = host.EndsWith("/") ? host.Substring(0, host.Length - 1) : host;
|
|
||||||
|
|
||||||
var client = WebRequest.Create(host + path + querystring);
|
|
||||||
client.Method = method;
|
|
||||||
|
|
||||||
byte[] formData = null;
|
|
||||||
if (formParams.Count > 0)
|
|
||||||
{
|
|
||||||
string formDataBoundary = String.Format("----------{0:N}", Guid.NewGuid());
|
|
||||||
client.ContentType = "multipart/form-data; boundary=" + formDataBoundary;
|
|
||||||
formData = GetMultipartFormData(formParams, formDataBoundary);
|
|
||||||
client.ContentLength = formData.Length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client.ContentType = "application/json";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var headerParamsItem in headerParams)
|
|
||||||
{
|
|
||||||
client.Headers.Add(headerParamsItem.Key, headerParamsItem.Value);
|
|
||||||
}
|
|
||||||
foreach (var defaultHeaderMapItem in defaultHeaderMap.Where(defaultHeaderMapItem => !headerParams.ContainsKey(defaultHeaderMapItem.Key)))
|
|
||||||
{
|
|
||||||
client.Headers.Add(defaultHeaderMapItem.Key, defaultHeaderMapItem.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (method)
|
|
||||||
{
|
|
||||||
case "GET":
|
|
||||||
break;
|
|
||||||
case "POST":
|
|
||||||
case "PATCH":
|
|
||||||
case "PUT":
|
|
||||||
case "DELETE":
|
|
||||||
using (Stream requestStream = client.GetRequestStream())
|
|
||||||
{
|
|
||||||
if (formData != null)
|
|
||||||
{
|
|
||||||
requestStream.Write(formData, 0, formData.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
var swRequestWriter = new StreamWriter(requestStream);
|
|
||||||
swRequestWriter.Write(serialize(body));
|
|
||||||
swRequestWriter.Close();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ApiException(500, "unknown method type " + method);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var webResponse = (HttpWebResponse)client.GetResponse();
|
|
||||||
if (webResponse.StatusCode != HttpStatusCode.OK)
|
|
||||||
{
|
|
||||||
webResponse.Close();
|
|
||||||
throw new ApiException((int)webResponse.StatusCode, webResponse.StatusDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (binaryResponse)
|
|
||||||
{
|
|
||||||
using (var memoryStream = new MemoryStream())
|
|
||||||
{
|
|
||||||
webResponse.GetResponseStream().CopyTo(memoryStream);
|
|
||||||
return memoryStream.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
using (var responseReader = new StreamReader(webResponse.GetResponseStream()))
|
|
||||||
{
|
|
||||||
var responseData = responseReader.ReadToEnd();
|
|
||||||
return responseData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(WebException ex)
|
|
||||||
{
|
|
||||||
var response = ex.Response as HttpWebResponse;
|
|
||||||
int statusCode = 0;
|
|
||||||
if (response != null)
|
|
||||||
{
|
|
||||||
statusCode = (int)response.StatusCode;
|
|
||||||
response.Close();
|
|
||||||
}
|
|
||||||
throw new ApiException(statusCode, ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
|
|
||||||
{
|
|
||||||
Stream formDataStream = new System.IO.MemoryStream();
|
|
||||||
bool needsCLRF = false;
|
|
||||||
|
|
||||||
foreach (var param in postParameters)
|
|
||||||
{
|
|
||||||
// Thanks to feedback from commenters, add a CRLF to allow multiple parameters to be added.
|
|
||||||
// Skip it on the first parameter, add it to subsequent parameters.
|
|
||||||
if (needsCLRF)
|
|
||||||
formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n"));
|
|
||||||
|
|
||||||
needsCLRF = true;
|
|
||||||
|
|
||||||
if (param.Value is byte[])
|
|
||||||
{
|
|
||||||
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n",
|
|
||||||
boundary,
|
|
||||||
param.Key,
|
|
||||||
"application/octet-stream");
|
|
||||||
formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData));
|
|
||||||
|
|
||||||
// Write the file data directly to the Stream, rather than serializing it to a string.
|
|
||||||
formDataStream.Write((param.Value as byte[]), 0, (param.Value as byte[]).Length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
|
|
||||||
boundary,
|
|
||||||
param.Key,
|
|
||||||
param.Value);
|
|
||||||
formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the end of the request. Start with a newline
|
|
||||||
string footer = "\r\n--" + boundary + "--\r\n";
|
|
||||||
formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
|
|
||||||
|
|
||||||
// Dump the Stream into a byte[]
|
|
||||||
formDataStream.Position = 0;
|
|
||||||
byte[] formData = new byte[formDataStream.Length];
|
|
||||||
formDataStream.Read(formData, 0, formData.Length);
|
|
||||||
formDataStream.Close();
|
|
||||||
|
|
||||||
return formData;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -2,19 +2,19 @@ using System;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
{{#models}}
|
{{#models}}
|
||||||
{{#model}}
|
{{#model}}
|
||||||
namespace {{package}} {
|
namespace {{package}} {
|
||||||
|
[DataContract]
|
||||||
public class {{classname}} {
|
public class {{classname}} {
|
||||||
{{#vars}}
|
{{#vars}}
|
||||||
|
{{#description}}/* {{{description}}} */{{/description}}
|
||||||
{{#description}}/* {{{description}}} */
|
[DataMember(Name="{{baseName}}", EmitDefaultValue=false)]
|
||||||
{{/description}}
|
|
||||||
public {{{datatype}}} {{name}} { get; set; }
|
public {{{datatype}}} {{name}} { get; set; }
|
||||||
|
|
||||||
{{/vars}}
|
{{/vars}}
|
||||||
|
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.Append("class {{classname}} {\n");
|
sb.Append("class {{classname}} {\n");
|
||||||
@ -27,4 +27,4 @@ namespace {{package}} {
|
|||||||
}
|
}
|
||||||
{{/model}}
|
{{/model}}
|
||||||
{{/models}}
|
{{/models}}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
{{#examples}}
|
{{#examples}}
|
||||||
<h3 class="field-label">Example data</h3>
|
<h3 class="field-label">Example data</h3>
|
||||||
<div class="example-data-content-type">Content-Type: {{{contentType}}}</div>
|
<div class="example-data-content-type">Content-Type: {{{contentType}}}</div>
|
||||||
<pre class="example"><code>{{{example}}}</code></pre>
|
<pre class="example"><code>{{example}}</code></pre>
|
||||||
{{/examples}}
|
{{/examples}}
|
||||||
</div> <!-- method -->
|
</div> <!-- method -->
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <ISO8601/ISO8601.h>
|
||||||
|
#import <JSONModel/JSONValueTransformer.h>
|
||||||
|
|
||||||
|
@interface JSONValueTransformer (ISO8601)
|
||||||
|
@end
|
@ -0,0 +1,10 @@
|
|||||||
|
#import "JSONValueTransformer+ISO8601.h"
|
||||||
|
|
||||||
|
@implementation JSONValueTransformer (ISO8601)
|
||||||
|
|
||||||
|
- (NSDate *) NSDateFromNSString:(NSString *)string
|
||||||
|
{
|
||||||
|
return [NSDate dateWithISO8601String:string];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
@ -2,3 +2,4 @@ platform :ios, '6.0'
|
|||||||
xcodeproj '{{projectName}}/{{projectName}}.xcodeproj'
|
xcodeproj '{{projectName}}/{{projectName}}.xcodeproj'
|
||||||
pod 'AFNetworking', '~> 2.1'
|
pod 'AFNetworking', '~> 2.1'
|
||||||
pod 'JSONModel', '~> 1.0'
|
pod 'JSONModel', '~> 1.0'
|
||||||
|
pod 'ISO8601'
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import "SWGObject.h"
|
|
||||||
|
|
||||||
@interface SWGDate : SWGObject {
|
|
||||||
@private
|
|
||||||
NSDate *_date;
|
|
||||||
}
|
|
||||||
@property(nonatomic, readonly) NSDate* date;
|
|
||||||
|
|
||||||
- (id) initWithValues: (NSString*)input;
|
|
||||||
-(NSString*) toString;
|
|
||||||
@end
|
|
@ -1,34 +0,0 @@
|
|||||||
#import "SWGDate.h"
|
|
||||||
|
|
||||||
@implementation SWGDate
|
|
||||||
|
|
||||||
@synthesize date = _date;
|
|
||||||
|
|
||||||
- (id) initWithValues:(NSString*)input {
|
|
||||||
if([input isKindOfClass:[NSString class]]){
|
|
||||||
NSDateFormatter* df = [NSDateFormatter new];
|
|
||||||
NSLocale *locale = [[NSLocale new]
|
|
||||||
initWithLocaleIdentifier:@"en_US_POSIX"];
|
|
||||||
[df setLocale:locale];
|
|
||||||
[df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
|
|
||||||
|
|
||||||
_date = [df dateFromString:input];
|
|
||||||
}
|
|
||||||
else if([input isKindOfClass:[NSNumber class]]) {
|
|
||||||
NSTimeInterval interval = [input doubleValue];
|
|
||||||
_date = [[NSDate alloc] initWithTimeIntervalSince1970:interval];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(NSString*) toString {
|
|
||||||
NSDateFormatter* df = [NSDateFormatter new];
|
|
||||||
NSLocale *locale = [[NSLocale new]
|
|
||||||
initWithLocaleIdentifier:@"en_US_POSIX"];
|
|
||||||
[df setLocale:locale];
|
|
||||||
[df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
|
|
||||||
|
|
||||||
return [df stringFromDate:_date];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
@ -69,6 +69,11 @@ static NSString * basePath = @"{{basePath}}";
|
|||||||
{{#returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)({{{returnType}}} output, NSError* error))completionBlock{{/returnBaseType}}
|
{{#returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)({{{returnType}}} output, NSError* error))completionBlock{{/returnBaseType}}
|
||||||
{{^returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)(NSError* error))completionBlock{{/returnBaseType}} {
|
{{^returnBaseType}}{{#hasParams}}completionHandler: {{/hasParams}}(void (^)(NSError* error))completionBlock{{/returnBaseType}} {
|
||||||
|
|
||||||
|
{{#allParams}}{{#required}}
|
||||||
|
// verify the required parameter '{{paramName}}' is set
|
||||||
|
NSAssert({{paramName}} != nil, @"Missing the required parameter `{{paramName}}` when calling {{nickname}}");
|
||||||
|
{{/required}}{{/allParams}}
|
||||||
|
|
||||||
NSMutableString* requestUrl = [NSMutableString stringWithFormat:@"%@{{path}}", basePath];
|
NSMutableString* requestUrl = [NSMutableString stringWithFormat:@"%@{{path}}", basePath];
|
||||||
|
|
||||||
// remove format in URL if needed
|
// remove format in URL if needed
|
||||||
|
@ -24,6 +24,8 @@ class APIClient {
|
|||||||
public static $GET = "GET";
|
public static $GET = "GET";
|
||||||
public static $PUT = "PUT";
|
public static $PUT = "PUT";
|
||||||
public static $DELETE = "DELETE";
|
public static $DELETE = "DELETE";
|
||||||
|
|
||||||
|
private static $default_header = array();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @var string timeout (second) of the HTTP request, by default set to 0, no timeout
|
* @var string timeout (second) of the HTTP request, by default set to 0, no timeout
|
||||||
@ -36,37 +38,110 @@ class APIClient {
|
|||||||
protected $user_agent = "PHP-Swagger";
|
protected $user_agent = "PHP-Swagger";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $host the address of the API server
|
* @param string $host Base url of the API server (optional)
|
||||||
* @param string $headerName a header to pass on requests
|
|
||||||
*/
|
*/
|
||||||
function __construct($host, $headerName = null, $headerValue = null) {
|
function __construct($host = null) {
|
||||||
$this->host = $host;
|
if ($host == null) {
|
||||||
$this->headerName = $headerName;
|
$this->host = '{{basePath}}';
|
||||||
$this->headerValue = $headerValue;
|
} else {
|
||||||
|
$this->host = $host;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the user agent of the API client
|
* add default header
|
||||||
*
|
*
|
||||||
* @param string $user_agent The user agent of the API client
|
* @param string $header_name header name (e.g. Token)
|
||||||
|
* @param string $header_value header value (e.g. 1z8wp3)
|
||||||
|
*/
|
||||||
|
public function addDefaultHeader($header_name, $header_value) {
|
||||||
|
if (!is_string($header_name))
|
||||||
|
throw new \InvalidArgumentException('Header name must be a string.');
|
||||||
|
|
||||||
|
self::$default_header[$header_name] = $header_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the default header
|
||||||
|
*
|
||||||
|
* @return array default header
|
||||||
|
*/
|
||||||
|
public function getDefaultHeader() {
|
||||||
|
return self::$default_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* delete the default header based on header name
|
||||||
|
*
|
||||||
|
* @param string $header_name header name (e.g. Token)
|
||||||
|
*/
|
||||||
|
public function deleteDefaultHeader($header_name) {
|
||||||
|
unset(self::$default_header[$header_name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the user agent of the api client
|
||||||
|
*
|
||||||
|
* @param string $user_agent the user agent of the api client
|
||||||
*/
|
*/
|
||||||
public function setUserAgent($user_agent) {
|
public function setUserAgent($user_agent) {
|
||||||
if (!is_string($user_agent)) {
|
if (!is_string($user_agent))
|
||||||
throw new Exception('User-agent must be a string.');
|
throw new \InvalidArgumentException('User-agent must be a string.');
|
||||||
}
|
|
||||||
$this->user_agent= $user_agent;
|
$this->user_agent= $user_agent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param integer $seconds Number of seconds before timing out [set to 0 for no timeout]
|
* @param integer $seconds Number of seconds before timing out [set to 0 for no timeout]
|
||||||
*/
|
*/
|
||||||
public function setTimeout($seconds) {
|
public function setTimeout($seconds) {
|
||||||
if (!is_numeric($seconds)) {
|
if (!is_numeric($seconds))
|
||||||
throw new Exception('Timeout variable must be numeric.');
|
throw new \InvalidArgumentException('Timeout variable must be numeric.');
|
||||||
}
|
|
||||||
$this->curl_timeout = $seconds;
|
$this->curl_timeout = $seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get API key (with prefix if set)
|
||||||
|
* @param string key name
|
||||||
|
* @return string API key with the prefix
|
||||||
|
*/
|
||||||
|
public function getApiKeyWithPrefix($apiKey) {
|
||||||
|
if (Configuration::$apiKeyPrefix[$apiKey]) {
|
||||||
|
return Configuration::$apiKeyPrefix[$apiKey]." ".Configuration::$apiKey[$apiKey];
|
||||||
|
} else {
|
||||||
|
return Configuration::$apiKey[$apiKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update hearder and query param based on authentication setting
|
||||||
|
*
|
||||||
|
* @param array $headerParams header parameters (by ref)
|
||||||
|
* @param array $queryParams query parameters (by ref)
|
||||||
|
* @param array $authSettings array of authentication scheme (e.g ['api_key'])
|
||||||
|
*/
|
||||||
|
public function updateParamsForAuth(&$headerParams, &$queryParams, $authSettings)
|
||||||
|
{
|
||||||
|
if (count($authSettings) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// one endpoint can have more than 1 auth settings
|
||||||
|
foreach($authSettings as $auth) {
|
||||||
|
// determine which one to use
|
||||||
|
switch($auth) {
|
||||||
|
{{#authMethods}}
|
||||||
|
case '{{name}}':
|
||||||
|
{{#isApiKey}}{{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode(Configuration::$username.":".Configuration::$password);{{/isBasic}}
|
||||||
|
{{#isOAuth}}//TODO support oauth{{/isOAuth}}
|
||||||
|
break;
|
||||||
|
{{/authMethods}}
|
||||||
|
default:
|
||||||
|
//TODO show warning about security definition not found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $resourcePath path to method endpoint
|
* @param string $resourcePath path to method endpoint
|
||||||
* @param string $method method to call
|
* @param string $method method to call
|
||||||
@ -76,23 +151,22 @@ class APIClient {
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function callAPI($resourcePath, $method, $queryParams, $postData,
|
public function callAPI($resourcePath, $method, $queryParams, $postData,
|
||||||
$headerParams) {
|
$headerParams, $authSettings) {
|
||||||
|
|
||||||
$headers = array();
|
$headers = array();
|
||||||
|
|
||||||
# Allow API key from $headerParams to override default
|
# determine authentication setting
|
||||||
$added_api_key = False;
|
$this->updateParamsForAuth($headerParams, $queryParams, $authSettings);
|
||||||
|
|
||||||
|
# construct the http header
|
||||||
if ($headerParams != null) {
|
if ($headerParams != null) {
|
||||||
|
# add default header
|
||||||
|
$headerParams = array_merge((array)self::$default_header, $headerParams);
|
||||||
|
|
||||||
foreach ($headerParams as $key => $val) {
|
foreach ($headerParams as $key => $val) {
|
||||||
$headers[] = "$key: $val";
|
$headers[] = "$key: $val";
|
||||||
if ($key == $this->headerName) {
|
|
||||||
$added_api_key = True;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! $added_api_key && $this->headerName != null) {
|
|
||||||
$headers[] = $this->headerName . ": " . $this->headerValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// form data
|
// form data
|
||||||
if ($postData and in_array('Content-Type: application/x-www-form-urlencoded', $headers)) {
|
if ($postData and in_array('Content-Type: application/x-www-form-urlencoded', $headers)) {
|
||||||
@ -111,6 +185,7 @@ class APIClient {
|
|||||||
}
|
}
|
||||||
// return the result on success, rather than just TRUE
|
// return the result on success, rather than just TRUE
|
||||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||||
|
|
||||||
if (! empty($queryParams)) {
|
if (! empty($queryParams)) {
|
||||||
@ -130,7 +205,7 @@ class APIClient {
|
|||||||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
|
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
|
||||||
} else if ($method != self::$GET) {
|
} else if ($method != self::$GET) {
|
||||||
throw new Exception('Method ' . $method . ' is not recognized.');
|
throw new APIClientException('Method ' . $method . ' is not recognized.');
|
||||||
}
|
}
|
||||||
curl_setopt($curl, CURLOPT_URL, $url);
|
curl_setopt($curl, CURLOPT_URL, $url);
|
||||||
|
|
||||||
@ -261,7 +336,6 @@ class APIClient {
|
|||||||
* @param string $class class name is passed as a string
|
* @param string $class class name is passed as a string
|
||||||
* @return object an instance of $class
|
* @return object an instance of $class
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static function deserialize($data, $class)
|
public static function deserialize($data, $class)
|
||||||
{
|
{
|
||||||
if (null === $data) {
|
if (null === $data) {
|
||||||
@ -304,5 +378,37 @@ class APIClient {
|
|||||||
return $deserialized;
|
return $deserialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return the header 'Accept' based on an array of Accept provided
|
||||||
|
*
|
||||||
|
* @param array[string] $accept Array of header
|
||||||
|
* @return string Accept (e.g. application/json)
|
||||||
|
*/
|
||||||
|
public static function selectHeaderAccept($accept) {
|
||||||
|
if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) {
|
||||||
|
return NULL;
|
||||||
|
} elseif (preg_grep("/application\/json/i", $accept)) {
|
||||||
|
return 'application/json';
|
||||||
|
} else {
|
||||||
|
return implode(',', $accept);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return the content type based on an array of content-type provided
|
||||||
|
*
|
||||||
|
* @param array[string] content_type_array Array fo content-type
|
||||||
|
* @return string Content-Type (e.g. application/json)
|
||||||
|
*/
|
||||||
|
public static function selectHeaderContentType($content_type) {
|
||||||
|
if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) {
|
||||||
|
return 'application/json';
|
||||||
|
} elseif (preg_grep("/application\/json/i", $content_type)) {
|
||||||
|
return 'application/json';
|
||||||
|
} else {
|
||||||
|
return implode(',', $content_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ class {{classname}} {
|
|||||||
{{#allParams}}{{#required}}
|
{{#allParams}}{{#required}}
|
||||||
// verify the required parameter '{{paramName}}' is set
|
// verify the required parameter '{{paramName}}' is set
|
||||||
if (${{paramName}} === null) {
|
if (${{paramName}} === null) {
|
||||||
throw new \Exception("Missing the required parameter ${{paramName}} when calling {{nickname}}");
|
throw new \InvalidArgumentException('Missing the required parameter ${{paramName}} when calling {{nickname}}');
|
||||||
}
|
}
|
||||||
{{/required}}{{/allParams}}
|
{{/required}}{{/allParams}}
|
||||||
|
|
||||||
@ -54,12 +54,11 @@ class {{classname}} {
|
|||||||
$queryParams = array();
|
$queryParams = array();
|
||||||
$headerParams = array();
|
$headerParams = array();
|
||||||
$formParams = array();
|
$formParams = array();
|
||||||
$_header_accept = '{{#produces}}{{mediaType}}{{#hasMore}}, {{/hasMore}}{{/produces}}';
|
$_header_accept = $this->apiClient->selectHeaderAccept(array({{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}));
|
||||||
if ($_header_accept !== '') {
|
if (!is_null($_header_accept)) {
|
||||||
$headerParams['Accept'] = $_header_accept;
|
$headerParams['Accept'] = $_header_accept;
|
||||||
}
|
}
|
||||||
$_header_content_type = array({{#consumes}}'{{mediaType}}'{{#hasMore}},{{/hasMore}}{{/consumes}});
|
$headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array({{#consumes}}'{{mediaType}}'{{#hasMore}},{{/hasMore}}{{/consumes}}));
|
||||||
$headerParams['Content-Type'] = count($_header_content_type) > 0 ? $_header_content_type[0] : 'application/json';
|
|
||||||
|
|
||||||
{{#queryParams}}// query params
|
{{#queryParams}}// query params
|
||||||
if(${{paramName}} !== null) {
|
if(${{paramName}} !== null) {
|
||||||
@ -92,18 +91,20 @@ class {{classname}} {
|
|||||||
$httpBody = $formParams;
|
$httpBody = $formParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// authentication setting, if any
|
||||||
|
$authSettings = array({{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}});
|
||||||
|
|
||||||
// make the API Call
|
// make the API Call
|
||||||
$response = $this->apiClient->callAPI($resourcePath, $method,
|
$response = $this->apiClient->callAPI($resourcePath, $method,
|
||||||
$queryParams, $httpBody,
|
$queryParams, $httpBody,
|
||||||
$headerParams);
|
$headerParams, $authSettings);
|
||||||
|
|
||||||
{{#returnType}}if(! $response) {
|
{{#returnType}}if(! $response) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$responseObject = $this->apiClient->deserialize($response,
|
$responseObject = $this->apiClient->deserialize($response,'{{returnType}}');
|
||||||
'{{returnType}}');
|
return $responseObject;{{/returnType}}
|
||||||
return $responseObject;{{/returnType}}
|
|
||||||
}
|
}
|
||||||
{{/operation}}
|
{{/operation}}
|
||||||
{{newline}}
|
{{newline}}
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright 2015 Reverb Technologies, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace {{invokerPackage}};
|
||||||
|
|
||||||
|
class Configuration {
|
||||||
|
|
||||||
|
public static $PATCH = "PATCH";
|
||||||
|
public static $POST = "POST";
|
||||||
|
public static $GET = "GET";
|
||||||
|
public static $PUT = "PUT";
|
||||||
|
public static $DELETE = "DELETE";
|
||||||
|
|
||||||
|
// authentication setting
|
||||||
|
public static $apiKey = array();
|
||||||
|
public static $apiKeyPrefix = array();
|
||||||
|
public static $username = '';
|
||||||
|
public static $password = '';
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -38,5 +38,37 @@ TODO
|
|||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
TODO
|
(Make sure you are running it inside of a [virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/))
|
||||||
|
|
||||||
|
You can run the tests in the current python platform:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ make test
|
||||||
|
[... magically installs dependencies and runs tests on your virtualenv]
|
||||||
|
Ran 7 tests in 19.289s
|
||||||
|
|
||||||
|
OK
|
||||||
|
```
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mvn integration-test -rf :PythonPetstoreClientTests
|
||||||
|
Using 2195432783 as seed
|
||||||
|
[INFO] ------------------------------------------------------------------------
|
||||||
|
[INFO] BUILD SUCCESS
|
||||||
|
[INFO] ------------------------------------------------------------------------
|
||||||
|
[INFO] Total time: 37.594 s
|
||||||
|
[INFO] Finished at: 2015-05-16T18:00:35+08:00
|
||||||
|
[INFO] Final Memory: 11M/156M
|
||||||
|
[INFO] ------------------------------------------------------------------------
|
||||||
|
```
|
||||||
|
If you want to run the tests in all the python platforms:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ make test-all
|
||||||
|
[... tox creates a virtualenv for every platform and runs tests inside of each]
|
||||||
|
py27: commands succeeded
|
||||||
|
py34: commands succeeded
|
||||||
|
congratulations :)
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
# import apis into api package
|
||||||
|
{{#apiInfo}}{{#apis}}from .{{classVarName}} import {{classname}}
|
||||||
|
{{/apis}}{{/apiInfo}}
|
@ -1,13 +1,5 @@
|
|||||||
#!/usr/bin/env python
|
from __future__ import absolute_import
|
||||||
"""Add all of the modules in the current directory to __all__"""
|
|
||||||
import os
|
|
||||||
|
|
||||||
{{#models}}{{#model}}
|
# import models into model package
|
||||||
from .{{classVarName}} import {{classname}}
|
{{#models}}{{#model}}from .{{classVarName}} import {{classname}}
|
||||||
{{/model}}{{/models}}
|
{{/model}}{{/models}}
|
||||||
|
|
||||||
__all__ = []
|
|
||||||
|
|
||||||
for module in os.listdir(os.path.dirname(__file__)):
|
|
||||||
if module != '__init__.py' and module[-3:] == '.py':
|
|
||||||
__all__.append(module[:-3])
|
|
||||||
|
@ -1,22 +1,10 @@
|
|||||||
#!/usr/bin/env python
|
from __future__ import absolute_import
|
||||||
"""Add all of the modules in the current directory to __all__"""
|
|
||||||
import os
|
|
||||||
|
|
||||||
# import models into package
|
# import models into sdk package
|
||||||
{{#models}}{{#model}}
|
{{#models}}{{#model}}from .models.{{classVarName}} import {{classname}}
|
||||||
from .models.{{classVarName}} import {{classname}}
|
|
||||||
{{/model}}{{/models}}
|
{{/model}}{{/models}}
|
||||||
|
# import apis into sdk package
|
||||||
# import apis into package
|
{{#apiInfo}}{{#apis}}from .apis.{{classVarName}} import {{classname}}
|
||||||
{{#apiInfo}}{{#apis}}
|
|
||||||
from .{{classVarName}} import {{classname}}
|
|
||||||
{{/apis}}{{/apiInfo}}
|
{{/apis}}{{/apiInfo}}
|
||||||
|
|
||||||
# import ApiClient
|
# import ApiClient
|
||||||
from .swagger import ApiClient
|
from .swagger import ApiClient
|
||||||
|
|
||||||
__all__ = []
|
|
||||||
|
|
||||||
for module in os.listdir(os.path.dirname(__file__)):
|
|
||||||
if module != '__init__.py' and module[-3:] == '.py':
|
|
||||||
__all__.append(module[:-3])
|
|
||||||
|
@ -19,100 +19,74 @@ Copyright 2015 Reverb Technologies, Inc.
|
|||||||
|
|
||||||
NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
|
NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import urllib
|
|
||||||
|
|
||||||
from models import *
|
# python 2 and python 3 compatibility library
|
||||||
|
from six import iteritems
|
||||||
|
|
||||||
|
from ..util import remove_none
|
||||||
|
|
||||||
{{#operations}}
|
{{#operations}}
|
||||||
class {{classname}}(object):
|
class {{classname}}(object):
|
||||||
|
|
||||||
def __init__(self, apiClient):
|
def __init__(self, api_client):
|
||||||
self.apiClient = apiClient
|
self.api_client = api_client
|
||||||
|
|
||||||
{{newline}}
|
|
||||||
{{#operation}}
|
{{#operation}}
|
||||||
def {{nickname}}(self, {{#requiredParams}}{{paramName}}{{#defaultValue}} = None{{/defaultValue}}, {{/requiredParams}}**kwargs):
|
def {{nickname}}(self, {{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}**kwargs):
|
||||||
"""{{{summary}}}
|
"""
|
||||||
|
{{{summary}}}
|
||||||
{{{notes}}}
|
{{{notes}}}
|
||||||
|
|
||||||
Args:
|
{{#allParams}}:param {{dataType}} {{paramName}}: {{{description}}} {{#required}}(required){{/required}}{{#optional}}(optional){{/optional}}
|
||||||
{{#allParams}}{{paramName}}, {{dataType}}: {{{description}}} {{^optional}}(required){{/optional}}{{#optional}}(optional){{/optional}}
|
{{/allParams}}
|
||||||
{{/allParams}}
|
:return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}}
|
||||||
|
|
||||||
Returns: {{returnType}}
|
|
||||||
"""
|
"""
|
||||||
|
{{#allParams}}{{#required}}
|
||||||
allParams = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}]
|
# verify the required parameter '{{paramName}}' is set
|
||||||
|
if {{paramName}} is None:
|
||||||
|
raise ValueError("Missing the required parameter `{{paramName}}` when calling `{{nickname}}`")
|
||||||
|
{{/required}}{{/allParams}}
|
||||||
|
all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}]
|
||||||
|
|
||||||
params = locals()
|
params = locals()
|
||||||
for (key, val) in params['kwargs'].iteritems():
|
for key, val in iteritems(params['kwargs']):
|
||||||
if key not in allParams:
|
if key not in all_params:
|
||||||
raise TypeError("Got an unexpected keyword argument '%s' to method {{nickname}}" % key)
|
raise TypeError("Got an unexpected keyword argument '%s' to method {{nickname}}" % key)
|
||||||
params[key] = val
|
params[key] = val
|
||||||
del params['kwargs']
|
del params['kwargs']
|
||||||
|
|
||||||
resourcePath = '{{path}}'
|
resource_path = '{{path}}'.replace('{format}', 'json')
|
||||||
resourcePath = resourcePath.replace('{format}', 'json')
|
|
||||||
method = '{{httpMethod}}'
|
method = '{{httpMethod}}'
|
||||||
|
|
||||||
queryParams = {}
|
path_params = remove_none(dict({{#pathParams}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/pathParams}}))
|
||||||
headerParams = {}
|
query_params = remove_none(dict({{#queryParams}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/queryParams}}))
|
||||||
formParams = {}
|
header_params = remove_none(dict({{#headerParams}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/headerParams}}))
|
||||||
files = {}
|
form_params = remove_none(dict({{#formParams}}{{^isFile}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/isFile}}{{/formParams}}))
|
||||||
bodyParam = None
|
files = remove_none(dict({{#formParams}}{{#isFile}}{{baseName}}=params.get('{{paramName}}'){{#hasMore}}, {{/hasMore}}{{/isFile}}{{/formParams}}))
|
||||||
|
body_params = {{#bodyParam}}params.get('{{paramName}}'){{/bodyParam}}{{^bodyParam}}None{{/bodyParam}}
|
||||||
|
|
||||||
accepts = [{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]
|
accepts = [{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]
|
||||||
headerParams['Accept'] = ', '.join(accepts)
|
header_params['Accept'] = ', '.join(accepts)
|
||||||
|
|
||||||
content_types = [{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]
|
content_types = [{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]
|
||||||
headerParams['Content-Type'] = content_types[0] if len(content_types) > 0 else 'application/json'
|
header_params['Content-Type'] = content_types[0] if len(content_types) > 0 else 'application/json'
|
||||||
|
|
||||||
{{#queryParams}}
|
|
||||||
if ('{{paramName}}' in params):
|
|
||||||
queryParams['{{baseName}}'] = self.apiClient.toPathValue(params['{{paramName}}'])
|
|
||||||
{{/queryParams}}
|
|
||||||
|
|
||||||
{{#headerParams}}
|
|
||||||
if ('{{paramName}}' in params):
|
|
||||||
headerParams['{{baseName}}'] = params['{{paramName}}']
|
|
||||||
{{/headerParams}}
|
|
||||||
|
|
||||||
{{#pathParams}}
|
|
||||||
if ('{{paramName}}' in params):
|
|
||||||
replacement = str(self.apiClient.toPathValue(params['{{paramName}}']))
|
|
||||||
replacement = urllib.quote(replacement)
|
|
||||||
resourcePath = resourcePath.replace('{' + '{{baseName}}' + '}',
|
|
||||||
replacement)
|
|
||||||
{{/pathParams}}
|
|
||||||
|
|
||||||
{{#formParams}}
|
|
||||||
if ('{{paramName}}' in params):
|
|
||||||
{{#notFile}}formParams['{{baseName}}'] = params['{{paramName}}']{{/notFile}}{{#isFile}}files['{{baseName}}'] = params['{{paramName}}']{{/isFile}}
|
|
||||||
{{/formParams}}
|
|
||||||
|
|
||||||
{{#bodyParam}}
|
|
||||||
if ('{{paramName}}' in params):
|
|
||||||
bodyParam = params['{{paramName}}']
|
|
||||||
{{/bodyParam}}
|
|
||||||
|
|
||||||
postData = (formParams if formParams else bodyParam)
|
|
||||||
|
|
||||||
response = self.apiClient.callAPI(resourcePath, method, queryParams,
|
|
||||||
postData, headerParams, files=files)
|
|
||||||
|
|
||||||
|
response = self.api_client.call_api(resource_path, method, path_params, query_params, header_params,
|
||||||
|
body=body_params, post_params=form_params, files=files,
|
||||||
|
response={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}})
|
||||||
{{#returnType}}
|
{{#returnType}}
|
||||||
if not response:
|
return response
|
||||||
return None
|
{{/returnType}}{{/operation}}
|
||||||
|
|
||||||
responseObject = self.apiClient.deserialize(response, '{{returnType}}')
|
|
||||||
return responseObject
|
|
||||||
{{/returnType}}
|
|
||||||
{{newline}}
|
|
||||||
{{newline}}
|
|
||||||
{{/operation}}
|
|
||||||
{{newline}}
|
|
||||||
{{/operations}}
|
{{/operations}}
|
||||||
{{newline}}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,33 +20,40 @@ Copyright 2015 Reverb Technologies, Inc.
|
|||||||
{{#model}}
|
{{#model}}
|
||||||
|
|
||||||
class {{classname}}(object):
|
class {{classname}}(object):
|
||||||
"""NOTE: This class is auto generated by the swagger code generator program.
|
"""
|
||||||
Do not edit the class manually."""
|
NOTE: This class is auto generated by the swagger code generator program.
|
||||||
|
Do not edit the class manually.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
Attributes:
|
Swagger model
|
||||||
swaggerTypes (dict): The key is attribute name and the value is attribute type.
|
|
||||||
attributeMap (dict): The key is attribute name and the value is json key in definition.
|
:param dict swaggerTypes: The key is attribute name and the value is attribute type.
|
||||||
|
:param dict attributeMap: The key is attribute name and the value is json key in definition.
|
||||||
"""
|
"""
|
||||||
self.swaggerTypes = {
|
self.swagger_types = {
|
||||||
{{#vars}}
|
{{#vars}}'{{name}}': '{{{datatype}}}'{{#hasMore}},
|
||||||
'{{name}}': '{{{datatype}}}'{{#hasMore}},
|
{{/hasMore}}{{/vars}}
|
||||||
{{/hasMore}}
|
|
||||||
{{/vars}}{{newline}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.attributeMap = {
|
self.attribute_map = {
|
||||||
{{#vars}}
|
{{#vars}}'{{name}}': '{{baseName}}'{{#hasMore}},
|
||||||
'{{name}}': '{{baseName}}'{{#hasMore}},{{/hasMore}}
|
{{/hasMore}}{{/vars}}
|
||||||
{{/vars}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{{#vars}}
|
{{#vars}}
|
||||||
{{#description}}#{{description}}
|
{{#description}}# {{description}}{{/description}}
|
||||||
{{/description}}
|
self.{{name}} = None # {{{datatype}}}
|
||||||
self.{{name}} = None # {{{datatype}}}
|
|
||||||
{{/vars}}
|
{{/vars}}
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
properties = []
|
||||||
|
for p in self.__dict__:
|
||||||
|
if p != 'swaggerTypes' and p != 'attributeMap':
|
||||||
|
properties.append('{prop}={val!r}'.format(prop=p, val=self.__dict__[p]))
|
||||||
|
|
||||||
|
return '<{name} {props}>'.format(name=__name__, props=' '.join(properties))
|
||||||
{{/model}}
|
{{/model}}
|
||||||
{{/models}}
|
{{/models}}
|
||||||
|
|
||||||
|
|
||||||
|
223
modules/swagger-codegen/src/main/resources/python/rest.mustache
Normal file
223
modules/swagger-codegen/src/main/resources/python/rest.mustache
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
import sys
|
||||||
|
import io
|
||||||
|
import json
|
||||||
|
|
||||||
|
# python 2 and python 3 compatibility library
|
||||||
|
from six import iteritems
|
||||||
|
|
||||||
|
try:
|
||||||
|
import urllib3
|
||||||
|
except ImportError:
|
||||||
|
raise ImportError('Swagger python client requires urllib3.')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# for python3
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
except ImportError:
|
||||||
|
# for python2
|
||||||
|
from urllib import urlencode
|
||||||
|
|
||||||
|
|
||||||
|
class RESTResponse(io.IOBase):
|
||||||
|
|
||||||
|
def __init__(self, resp):
|
||||||
|
self.urllib3_response = resp
|
||||||
|
self.status = resp.status
|
||||||
|
self.reason = resp.reason
|
||||||
|
self.data = resp.data
|
||||||
|
|
||||||
|
def getheaders(self):
|
||||||
|
"""
|
||||||
|
Returns a dictionary of the response headers.
|
||||||
|
"""
|
||||||
|
return self.urllib3_response.getheaders()
|
||||||
|
|
||||||
|
def getheader(self, name, default=None):
|
||||||
|
"""
|
||||||
|
Returns a given response header.
|
||||||
|
"""
|
||||||
|
return self.urllib3_response.getheader(name, default)
|
||||||
|
|
||||||
|
class RESTClientObject(object):
|
||||||
|
|
||||||
|
def __init__(self, pools_size=4):
|
||||||
|
self.pool_manager = urllib3.PoolManager(
|
||||||
|
num_pools=pools_size
|
||||||
|
)
|
||||||
|
|
||||||
|
def request(self, method, url, query_params=None, headers=None,
|
||||||
|
body=None, post_params=None):
|
||||||
|
"""
|
||||||
|
:param method: http request method
|
||||||
|
:param url: http request url
|
||||||
|
:param query_params: query parameters in the url
|
||||||
|
:param headers: http request headers
|
||||||
|
:param body: request json body, for `application/json`
|
||||||
|
:param post_params: request post parameters, `application/x-www-form-urlencode`
|
||||||
|
and `multipart/form-data`
|
||||||
|
:param raw_response: if return the raw response
|
||||||
|
"""
|
||||||
|
method = method.upper()
|
||||||
|
assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', 'PATCH']
|
||||||
|
|
||||||
|
if post_params and body:
|
||||||
|
raise ValueError("body parameter cannot be used with post_params parameter.")
|
||||||
|
|
||||||
|
post_params = post_params or {}
|
||||||
|
headers = headers or {}
|
||||||
|
|
||||||
|
if 'Content-Type' not in headers:
|
||||||
|
headers['Content-Type'] = 'application/json'
|
||||||
|
|
||||||
|
# For `POST`, `PUT`, `PATCH`
|
||||||
|
if method in ['POST', 'PUT', 'PATCH']:
|
||||||
|
if query_params:
|
||||||
|
url += '?' + urlencode(query_params)
|
||||||
|
if headers['Content-Type'] == 'application/json':
|
||||||
|
r = self.pool_manager.request(method, url,
|
||||||
|
body=json.dumps(body),
|
||||||
|
headers=headers)
|
||||||
|
if headers['Content-Type'] == 'application/x-www-form-urlencoded':
|
||||||
|
r = self.pool_manager.request(method, url,
|
||||||
|
fields=post_params,
|
||||||
|
encode_multipart=False,
|
||||||
|
headers=headers)
|
||||||
|
if headers['Content-Type'] == 'multipart/form-data':
|
||||||
|
# must del headers['Content-Type'], or the correct Content-Type
|
||||||
|
# which generated by urllib3 will be overwritten.
|
||||||
|
del headers['Content-Type']
|
||||||
|
r = self.pool_manager.request(method, url,
|
||||||
|
fields=post_params,
|
||||||
|
encode_multipart=True,
|
||||||
|
headers=headers)
|
||||||
|
# For `GET`, `HEAD`, `DELETE`
|
||||||
|
else:
|
||||||
|
r = self.pool_manager.request(method, url,
|
||||||
|
fields=query_params,
|
||||||
|
headers=headers)
|
||||||
|
r = RESTResponse(r)
|
||||||
|
|
||||||
|
if r.status not in range(200, 206):
|
||||||
|
raise ErrorResponse(r)
|
||||||
|
|
||||||
|
return self.process_response(r)
|
||||||
|
|
||||||
|
def process_response(self, response):
|
||||||
|
# In the python 3, the response.data is bytes.
|
||||||
|
# we need to decode it to string.
|
||||||
|
if sys.version_info > (3,):
|
||||||
|
data = response.data.decode('utf8')
|
||||||
|
else:
|
||||||
|
data = response.data
|
||||||
|
try:
|
||||||
|
resp = json.loads(data)
|
||||||
|
except ValueError:
|
||||||
|
resp = data
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
|
def GET(self, url, headers=None, query_params=None):
|
||||||
|
return self.request("GET", url, headers=headers, query_params=query_params)
|
||||||
|
|
||||||
|
def HEAD(self, url, headers=None, query_params=None):
|
||||||
|
return self.request("HEAD", url, headers=headers, query_params=query_params)
|
||||||
|
|
||||||
|
def DELETE(self, url, headers=None, query_params=None):
|
||||||
|
return self.request("DELETE", url, headers=headers, query_params=query_params)
|
||||||
|
|
||||||
|
def POST(self, url, headers=None, post_params=None, body=None):
|
||||||
|
return self.request("POST", url, headers=headers, post_params=post_params, body=body)
|
||||||
|
|
||||||
|
def PUT(self, url, headers=None, post_params=None, body=None):
|
||||||
|
return self.request("PUT", url, headers=headers, post_params=post_params, body=body)
|
||||||
|
|
||||||
|
def PATCH(self, url, headers=None, post_params=None, body=None):
|
||||||
|
return self.request("PATCH", url, headers=headers, post_params=post_params, body=body)
|
||||||
|
|
||||||
|
|
||||||
|
class ErrorResponse(Exception):
|
||||||
|
"""
|
||||||
|
Non-2xx HTTP response
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, http_resp):
|
||||||
|
self.status = http_resp.status
|
||||||
|
self.reason = http_resp.reason
|
||||||
|
self.body = http_resp.data
|
||||||
|
self.headers = http_resp.getheaders()
|
||||||
|
|
||||||
|
# In the python 3, the self.body is bytes.
|
||||||
|
# we need to decode it to string.
|
||||||
|
if sys.version_info > (3,):
|
||||||
|
data = self.body.decode('utf8')
|
||||||
|
else:
|
||||||
|
data = self.body
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.body = json.loads(data)
|
||||||
|
except ValueError:
|
||||||
|
self.body = data
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""
|
||||||
|
Custom error response messages
|
||||||
|
"""
|
||||||
|
return "({0})\nReason: {1}\nHeader: {2}\nBody: {3}\n".\
|
||||||
|
format(self.status, self.reason, self.headers, self.body)
|
||||||
|
|
||||||
|
class RESTClient(object):
|
||||||
|
"""
|
||||||
|
A class with all class methods to perform JSON requests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
IMPL = RESTClientObject()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def request(cls, *n, **kw):
|
||||||
|
"""
|
||||||
|
Perform a REST request and parse the response.
|
||||||
|
"""
|
||||||
|
return cls.IMPL.request(*n, **kw)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def GET(cls, *n, **kw):
|
||||||
|
"""
|
||||||
|
Perform a GET request using `RESTClient.request()`.
|
||||||
|
"""
|
||||||
|
return cls.IMPL.GET(*n, **kw)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def HEAD(cls, *n, **kw):
|
||||||
|
"""
|
||||||
|
Perform a HEAD request using `RESTClient.request()`.
|
||||||
|
"""
|
||||||
|
return cls.IMPL.GET(*n, **kw)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def POST(cls, *n, **kw):
|
||||||
|
"""
|
||||||
|
Perform a POST request using `RESTClient.request()`
|
||||||
|
"""
|
||||||
|
return cls.IMPL.POST(*n, **kw)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def PUT(cls, *n, **kw):
|
||||||
|
"""
|
||||||
|
Perform a PUT request using `RESTClient.request()`
|
||||||
|
"""
|
||||||
|
return cls.IMPL.PUT(*n, **kw)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def PATCH(cls, *n, **kw):
|
||||||
|
"""
|
||||||
|
Perform a PATCH request using `RESTClient.request()`
|
||||||
|
"""
|
||||||
|
return cls.IMPL.PATCH(*n, **kw)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def DELETE(cls, *n, **kw):
|
||||||
|
"""
|
||||||
|
Perform a DELETE request using `RESTClient.request()`
|
||||||
|
"""
|
||||||
|
return cls.IMPL.DELETE(*n, **kw)
|
@ -12,7 +12,7 @@ from setuptools import setup, find_packages
|
|||||||
# Try reading the setuptools documentation:
|
# Try reading the setuptools documentation:
|
||||||
# http://pypi.python.org/pypi/setuptools
|
# http://pypi.python.org/pypi/setuptools
|
||||||
|
|
||||||
REQUIRES = []
|
REQUIRES = ["urllib3 >= 1.10", "six >= 1.9"]
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="{{module}}",
|
name="{{module}}",
|
||||||
@ -30,3 +30,11 @@ setup(
|
|||||||
)
|
)
|
||||||
|
|
||||||
{{/hasMore}}{{/apis}}{{/apiInfo}}
|
{{/hasMore}}{{/apis}}{{/apiInfo}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,118 +6,109 @@ server communication, and is invariant across implementations. Specifics of
|
|||||||
the methods and models for each application are generated from the Swagger
|
the methods and models for each application are generated from the Swagger
|
||||||
templates."""
|
templates."""
|
||||||
|
|
||||||
import sys
|
from __future__ import absolute_import
|
||||||
|
from . import models
|
||||||
|
from .rest import RESTClient
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import urllib
|
import urllib
|
||||||
import urllib2
|
|
||||||
import httplib
|
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import random
|
import random
|
||||||
import string
|
|
||||||
import models
|
# python 2 and python 3 compatibility library
|
||||||
|
from six import iteritems
|
||||||
|
|
||||||
|
try:
|
||||||
|
# for python3
|
||||||
|
from urllib.parse import quote
|
||||||
|
except ImportError:
|
||||||
|
# for python2
|
||||||
|
from urllib import quote
|
||||||
|
|
||||||
|
|
||||||
class ApiClient(object):
|
class ApiClient(object):
|
||||||
"""Generic API client for Swagger client library builds
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
host: The base path for the server to call
|
|
||||||
headerName: a header to pass when making calls to the API
|
|
||||||
headerValue: a header value to pass when making calls to the API
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, host=None, headerName=None, headerValue=None):
|
Generic API client for Swagger client library builds
|
||||||
self.defaultHeaders = {}
|
|
||||||
if (headerName is not None):
|
:param host: The base path for the server to call
|
||||||
self.defaultHeaders[headerName] = headerValue
|
:param header_name: a header to pass when making calls to the API
|
||||||
|
:param header_value: a header value to pass when making calls to the API
|
||||||
|
"""
|
||||||
|
def __init__(self, host=None, header_name=None, header_value=None):
|
||||||
|
self.default_headers = {}
|
||||||
|
if header_name is not None:
|
||||||
|
self.default_headers[header_name] = header_value
|
||||||
self.host = host
|
self.host = host
|
||||||
self.cookie = None
|
self.cookie = None
|
||||||
self.boundary = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(30))
|
|
||||||
# Set default User-Agent.
|
# Set default User-Agent.
|
||||||
self.user_agent = 'Python-Swagger'
|
self.user_agent = 'Python-Swagger'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def user_agent(self):
|
def user_agent(self):
|
||||||
return self.defaultHeaders['User-Agent']
|
return self.default_headers['User-Agent']
|
||||||
|
|
||||||
@user_agent.setter
|
@user_agent.setter
|
||||||
def user_agent(self, value):
|
def user_agent(self, value):
|
||||||
self.defaultHeaders['User-Agent'] = value
|
self.default_headers['User-Agent'] = value
|
||||||
|
|
||||||
def setDefaultHeader(self, headerName, headerValue):
|
def set_default_header(self, header_name, header_value):
|
||||||
self.defaultHeaders[headerName] = headerValue
|
self.default_headers[header_name] = header_value
|
||||||
|
|
||||||
def callAPI(self, resourcePath, method, queryParams, postData,
|
def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None,
|
||||||
headerParams=None, files=None):
|
body=None, post_params=None, files=None, response=None):
|
||||||
|
|
||||||
url = self.host + resourcePath
|
|
||||||
|
|
||||||
mergedHeaderParams = self.defaultHeaders.copy()
|
|
||||||
mergedHeaderParams.update(headerParams)
|
|
||||||
headers = {}
|
|
||||||
if mergedHeaderParams:
|
|
||||||
for param, value in mergedHeaderParams.iteritems():
|
|
||||||
headers[param] = ApiClient.sanitizeForSerialization(value)
|
|
||||||
|
|
||||||
|
# headers parameters
|
||||||
|
headers = self.default_headers.copy()
|
||||||
|
headers.update(header_params)
|
||||||
if self.cookie:
|
if self.cookie:
|
||||||
headers['Cookie'] = ApiClient.sanitizeForSerialization(self.cookie)
|
headers['Cookie'] = self.cookie
|
||||||
|
if headers:
|
||||||
|
headers = ApiClient.sanitize_for_serialization(headers)
|
||||||
|
|
||||||
data = None
|
# path parameters
|
||||||
|
if path_params:
|
||||||
|
path_params = ApiClient.sanitize_for_serialization(path_params)
|
||||||
|
for k, v in iteritems(path_params):
|
||||||
|
replacement = quote(str(self.to_path_value(v)))
|
||||||
|
resource_path = resource_path.replace('{' + k + '}', replacement)
|
||||||
|
|
||||||
if queryParams:
|
# query parameters
|
||||||
# Need to remove None values, these should not be sent
|
if query_params:
|
||||||
sentQueryParams = {}
|
query_params = ApiClient.sanitize_for_serialization(query_params)
|
||||||
for param, value in queryParams.items():
|
query_params = {k: self.to_path_value(v) for k, v in iteritems(query_params)}
|
||||||
if value is not None:
|
|
||||||
sentQueryParams[param] = ApiClient.sanitizeForSerialization(value)
|
|
||||||
url = url + '?' + urllib.urlencode(sentQueryParams)
|
|
||||||
|
|
||||||
if method in ['GET']:
|
# post parameters
|
||||||
#Options to add statements later on and for compatibility
|
if post_params:
|
||||||
pass
|
post_params = self.prepare_post_parameters(post_params, files)
|
||||||
|
post_params = ApiClient.sanitize_for_serialization(post_params)
|
||||||
|
|
||||||
elif method in ['POST', 'PUT', 'DELETE']:
|
# body
|
||||||
if postData:
|
if body:
|
||||||
postData = ApiClient.sanitizeForSerialization(postData)
|
body = ApiClient.sanitize_for_serialization(body)
|
||||||
if 'Content-Type' not in headers:
|
|
||||||
headers['Content-Type'] = 'application/json'
|
|
||||||
data = json.dumps(postData)
|
|
||||||
elif headers['Content-Type'] == 'application/json':
|
|
||||||
data = json.dumps(postData)
|
|
||||||
elif headers['Content-Type'] == 'multipart/form-data':
|
|
||||||
data = self.buildMultipartFormData(postData, files)
|
|
||||||
headers['Content-Type'] = 'multipart/form-data; boundary={0}'.format(self.boundary)
|
|
||||||
headers['Content-length'] = str(len(data))
|
|
||||||
else:
|
|
||||||
data = urllib.urlencode(postData)
|
|
||||||
|
|
||||||
|
# request url
|
||||||
|
url = self.host + resource_path
|
||||||
|
|
||||||
|
# perform request and return response
|
||||||
|
response_data = self.request(method, url, query_params=query_params, headers=headers,
|
||||||
|
post_params=post_params, body=body)
|
||||||
|
|
||||||
|
# deserialize response data
|
||||||
|
if response:
|
||||||
|
return self.deserialize(response_data, response)
|
||||||
else:
|
else:
|
||||||
raise Exception('Method ' + method + ' is not recognized.')
|
return None
|
||||||
|
|
||||||
request = MethodRequest(method=method, url=url, headers=headers,
|
def to_path_value(self, obj):
|
||||||
data=data)
|
"""
|
||||||
|
Convert a string or object to a path-friendly value
|
||||||
|
|
||||||
|
:param obj: object or string value
|
||||||
|
|
||||||
# Make the request
|
:return string: quoted value
|
||||||
response = urllib2.urlopen(request)
|
|
||||||
if 'Set-Cookie' in response.headers:
|
|
||||||
self.cookie = response.headers['Set-Cookie']
|
|
||||||
string = response.read()
|
|
||||||
|
|
||||||
try:
|
|
||||||
data = json.loads(string)
|
|
||||||
except ValueError: # PUT requests don't return anything
|
|
||||||
data = None
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
def toPathValue(self, obj):
|
|
||||||
"""Convert a string or object to a path-friendly value
|
|
||||||
Args:
|
|
||||||
obj -- object or string value
|
|
||||||
Returns:
|
|
||||||
string -- quoted value
|
|
||||||
"""
|
"""
|
||||||
if type(obj) == list:
|
if type(obj) == list:
|
||||||
return ','.join(obj)
|
return ','.join(obj)
|
||||||
@ -125,12 +116,12 @@ class ApiClient(object):
|
|||||||
return str(obj)
|
return str(obj)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sanitizeForSerialization(obj):
|
def sanitize_for_serialization(obj):
|
||||||
"""
|
"""
|
||||||
Sanitize an object for Request.
|
Sanitize an object for Request.
|
||||||
|
|
||||||
If obj is None, return None.
|
If obj is None, return None.
|
||||||
If obj is str, int, long, float, bool, return directly.
|
If obj is str, int, float, bool, return directly.
|
||||||
If obj is datetime.datetime, datetime.date convert to string in iso8601 format.
|
If obj is datetime.datetime, datetime.date convert to string in iso8601 format.
|
||||||
If obj is list, santize each element in the list.
|
If obj is list, santize each element in the list.
|
||||||
If obj is dict, return the dict.
|
If obj is dict, return the dict.
|
||||||
@ -138,113 +129,80 @@ class ApiClient(object):
|
|||||||
"""
|
"""
|
||||||
if isinstance(obj, type(None)):
|
if isinstance(obj, type(None)):
|
||||||
return None
|
return None
|
||||||
elif isinstance(obj, (str, int, long, float, bool, file)):
|
elif isinstance(obj, (str, int, float, bool, tuple)):
|
||||||
return obj
|
return obj
|
||||||
elif isinstance(obj, list):
|
elif isinstance(obj, list):
|
||||||
return [ApiClient.sanitizeForSerialization(subObj) for subObj in obj]
|
return [ApiClient.sanitize_for_serialization(sub_obj) for sub_obj in obj]
|
||||||
elif isinstance(obj, (datetime.datetime, datetime.date)):
|
elif isinstance(obj, (datetime.datetime, datetime.date)):
|
||||||
return obj.isoformat()
|
return obj.isoformat()
|
||||||
else:
|
else:
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
objDict = obj
|
obj_dict = obj
|
||||||
else:
|
else:
|
||||||
# Convert model obj to dict except attributes `swaggerTypes`, `attributeMap`
|
# Convert model obj to dict except attributes `swagger_types`, `attribute_map`
|
||||||
# and attributes which value is not None.
|
# and attributes which value is not None.
|
||||||
# Convert attribute name to json key in model definition for request.
|
# Convert attribute name to json key in model definition for request.
|
||||||
objDict = {obj.attributeMap[key]: val
|
obj_dict = {obj.attribute_map[key]: val
|
||||||
for key, val in obj.__dict__.iteritems()
|
for key, val in iteritems(obj.__dict__)
|
||||||
if key != 'swaggerTypes' and key != 'attributeMap' and val is not None}
|
if key != 'swagger_types' and key != 'attribute_map' and val is not None}
|
||||||
return {key: ApiClient.sanitizeForSerialization(val)
|
return {key: ApiClient.sanitize_for_serialization(val)
|
||||||
for (key, val) in objDict.iteritems()}
|
for key, val in iteritems(obj_dict)}
|
||||||
|
|
||||||
def buildMultipartFormData(self, postData, files):
|
def deserialize(self, obj, obj_class):
|
||||||
def escape_quotes(s):
|
"""
|
||||||
return s.replace('"', '\\"')
|
Derialize a JSON string into an object.
|
||||||
|
|
||||||
lines = []
|
:param obj: string or object to be deserialized
|
||||||
|
:param obj_class: class literal for deserialzied object, or string of class name
|
||||||
|
|
||||||
for name, value in postData.items():
|
:return object: deserialized object
|
||||||
lines.extend((
|
"""
|
||||||
'--{0}'.format(self.boundary),
|
# Have to accept obj_class as string or actual type. Type could be a
|
||||||
'Content-Disposition: form-data; name="{0}"'.format(escape_quotes(name)),
|
|
||||||
'',
|
|
||||||
str(value),
|
|
||||||
))
|
|
||||||
|
|
||||||
for name, filepath in files.items():
|
|
||||||
f = open(filepath, 'r')
|
|
||||||
filename = filepath.split('/')[-1]
|
|
||||||
mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
|
|
||||||
lines.extend((
|
|
||||||
'--{0}'.format(self.boundary),
|
|
||||||
'Content-Disposition: form-data; name="{0}"; filename="{1}"'.format(escape_quotes(name), escape_quotes(filename)),
|
|
||||||
'Content-Type: {0}'.format(mimetype),
|
|
||||||
'',
|
|
||||||
f.read()
|
|
||||||
))
|
|
||||||
|
|
||||||
lines.extend((
|
|
||||||
'--{0}--'.format(self.boundary),
|
|
||||||
''
|
|
||||||
))
|
|
||||||
return '\r\n'.join(lines)
|
|
||||||
|
|
||||||
def deserialize(self, obj, objClass):
|
|
||||||
"""Derialize a JSON string into an object.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
obj -- string or object to be deserialized
|
|
||||||
objClass -- class literal for deserialzied object, or string
|
|
||||||
of class name
|
|
||||||
Returns:
|
|
||||||
object -- deserialized object"""
|
|
||||||
|
|
||||||
# Have to accept objClass as string or actual type. Type could be a
|
|
||||||
# native Python type, or one of the model classes.
|
# native Python type, or one of the model classes.
|
||||||
if type(objClass) == str:
|
if type(obj_class) == str:
|
||||||
if 'list[' in objClass:
|
if 'list[' in obj_class:
|
||||||
match = re.match('list\[(.*)\]', objClass)
|
match = re.match('list\[(.*)\]', obj_class)
|
||||||
subClass = match.group(1)
|
sub_class = match.group(1)
|
||||||
return [self.deserialize(subObj, subClass) for subObj in obj]
|
return [self.deserialize(sub_obj, sub_class) for sub_obj in obj]
|
||||||
|
|
||||||
if (objClass in ['int', 'float', 'long', 'dict', 'list', 'str', 'bool', 'datetime']):
|
if obj_class in ['int', 'float', 'dict', 'list', 'str', 'bool', 'datetime']:
|
||||||
objClass = eval(objClass)
|
obj_class = eval(obj_class)
|
||||||
else: # not a native type, must be model class
|
else: # not a native type, must be model class
|
||||||
objClass = eval('models.' + objClass)
|
obj_class = eval('models.' + obj_class)
|
||||||
|
|
||||||
if objClass in [int, long, float, dict, list, str, bool]:
|
if obj_class in [int, float, dict, list, str, bool]:
|
||||||
return objClass(obj)
|
return obj_class(obj)
|
||||||
elif objClass == datetime:
|
elif obj_class == datetime:
|
||||||
return self.__parse_string_to_datetime(obj)
|
return self.__parse_string_to_datetime(obj)
|
||||||
|
|
||||||
instance = objClass()
|
instance = obj_class()
|
||||||
|
|
||||||
for attr, attrType in instance.swaggerTypes.iteritems():
|
for attr, attr_type in iteritems(instance.swagger_types):
|
||||||
if obj is not None and instance.attributeMap[attr] in obj and type(obj) in [list, dict]:
|
if obj is not None and instance.attribute_map[attr] in obj and type(obj) in [list, dict]:
|
||||||
value = obj[instance.attributeMap[attr]]
|
value = obj[instance.attribute_map[attr]]
|
||||||
if attrType in ['str', 'int', 'long', 'float', 'bool']:
|
if attr_type in ['str', 'int', 'float', 'bool']:
|
||||||
attrType = eval(attrType)
|
attr_type = eval(attr_type)
|
||||||
try:
|
try:
|
||||||
value = attrType(value)
|
value = attr_type(value)
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
value = unicode(value)
|
value = unicode(value)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
value = value
|
value = value
|
||||||
setattr(instance, attr, value)
|
setattr(instance, attr, value)
|
||||||
elif (attrType == 'datetime'):
|
elif attr_type == 'datetime':
|
||||||
setattr(instance, attr, self.__parse_string_to_datetime(value))
|
setattr(instance, attr, self.__parse_string_to_datetime(value))
|
||||||
elif 'list[' in attrType:
|
elif 'list[' in attr_type:
|
||||||
match = re.match('list\[(.*)\]', attrType)
|
match = re.match('list\[(.*)\]', attr_type)
|
||||||
subClass = match.group(1)
|
sub_class = match.group(1)
|
||||||
subValues = []
|
sub_values = []
|
||||||
if not value:
|
if not value:
|
||||||
setattr(instance, attr, None)
|
setattr(instance, attr, None)
|
||||||
else:
|
else:
|
||||||
for subValue in value:
|
for sub_value in value:
|
||||||
subValues.append(self.deserialize(subValue, subClass))
|
sub_values.append(self.deserialize(sub_value, sub_class))
|
||||||
setattr(instance, attr, subValues)
|
setattr(instance, attr, sub_values)
|
||||||
else:
|
else:
|
||||||
setattr(instance, attr, self.deserialize(value, attrType))
|
setattr(instance, attr, self.deserialize(value, attr_type))
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@ -260,16 +218,42 @@ class ApiClient(object):
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
return string
|
return string
|
||||||
|
|
||||||
class MethodRequest(urllib2.Request):
|
def request(self, method, url, query_params=None, headers=None, post_params=None, body=None):
|
||||||
def __init__(self, *args, **kwargs):
|
"""
|
||||||
"""Construct a MethodRequest. Usage is the same as for
|
Perform http request using RESTClient.
|
||||||
`urllib2.Request` except it also takes an optional `method`
|
"""
|
||||||
keyword argument. If supplied, `method` will be used instead of
|
if method == "GET":
|
||||||
the default."""
|
return RESTClient.GET(url, query_params=query_params, headers=headers)
|
||||||
|
elif method == "HEAD":
|
||||||
|
return RESTClient.HEAD(url, query_params=query_params, headers=headers)
|
||||||
|
elif method == "POST":
|
||||||
|
return RESTClient.POST(url, headers=headers, post_params=post_params, body=body)
|
||||||
|
elif method == "PUT":
|
||||||
|
return RESTClient.PUT(url, headers=headers, post_params=post_params, body=body)
|
||||||
|
elif method == "PATCH":
|
||||||
|
return RESTClient.PATCH(url, headers=headers, post_params=post_params, body=body)
|
||||||
|
elif method == "DELETE":
|
||||||
|
return RESTClient.DELETE(url, query_params=query_params, headers=headers)
|
||||||
|
else:
|
||||||
|
raise ValueError("http method must be `GET`, `HEAD`, `POST`, `PATCH`, `PUT` or `DELETE`")
|
||||||
|
|
||||||
|
def prepare_post_parameters(self, post_params=None, files=None):
|
||||||
|
params = {}
|
||||||
|
|
||||||
|
if post_params:
|
||||||
|
params.update(post_params)
|
||||||
|
|
||||||
|
if files:
|
||||||
|
for k, v in iteritems(files):
|
||||||
|
with open(v, 'rb') as f:
|
||||||
|
filename = os.path.basename(f.name)
|
||||||
|
filedata = f.read()
|
||||||
|
mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
|
||||||
|
params[k] = tuple([filename, filedata, mimetype])
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if 'method' in kwargs:
|
|
||||||
self.method = kwargs.pop('method')
|
|
||||||
return urllib2.Request.__init__(self, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_method(self):
|
|
||||||
return getattr(self, 'method', urllib2.Request.get_method(self))
|
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
from six import iteritems
|
||||||
|
|
||||||
|
def remove_none(obj):
|
||||||
|
if isinstance(obj, (list, tuple, set)):
|
||||||
|
return type(obj)(remove_none(x) for x in obj if x is not None)
|
||||||
|
elif isinstance(obj, dict):
|
||||||
|
return type(obj)((remove_none(k), remove_none(v))
|
||||||
|
for k, v in iteritems(obj) if k is not None and v is not None)
|
||||||
|
else:
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def inspect_vars(obj):
|
||||||
|
if not hasattr(obj, '__dict__'):
|
||||||
|
return obj
|
||||||
|
else:
|
||||||
|
return {k: inspect_vars(getattr(obj, k)) for k in dir(obj)}
|
@ -1,57 +1,59 @@
|
|||||||
require "uri"
|
require "uri"
|
||||||
|
|
||||||
|
module {{moduleName}}
|
||||||
{{#operations}}
|
{{#operations}}
|
||||||
class {{classname}}
|
class {{classname}}
|
||||||
basePath = "{{basePath}}"
|
basePath = "{{basePath}}"
|
||||||
# apiInvoker = APIInvoker
|
# apiInvoker = APIInvoker
|
||||||
{{#operation}}
|
{{#operation}}
|
||||||
{{newline}}
|
{{newline}}
|
||||||
# {{summary}}
|
# {{summary}}
|
||||||
# {{notes}}
|
# {{notes}}
|
||||||
{{#allParams}}{{#required}} # @param {{paramName}} {{description}}
|
{{#allParams}}{{#required}} # @param {{paramName}} {{description}}
|
||||||
{{/required}}{{/allParams}} # @param [Hash] opts the optional parameters
|
{{/required}}{{/allParams}} # @param [Hash] opts the optional parameters
|
||||||
{{#allParams}}{{^required}} # @option opts [{{dataType}}] :{{paramName}} {{description}}
|
{{#allParams}}{{^required}} # @option opts [{{dataType}}] :{{paramName}} {{description}}
|
||||||
{{/required}}{{/allParams}} # @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
|
{{/required}}{{/allParams}} # @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
|
||||||
def self.{{nickname}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}opts = {})
|
def self.{{nickname}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}opts = {})
|
||||||
{{#allParams}}{{#required}}
|
{{#allParams}}{{#required}}
|
||||||
# verify the required parameter '{{paramName}}' is set
|
# verify the required parameter '{{paramName}}' is set
|
||||||
raise "Missing the required parameter '{{paramName}}' when calling {{nickname}}" if {{{paramName}}}.nil?
|
raise "Missing the required parameter '{{paramName}}' when calling {{nickname}}" if {{{paramName}}}.nil?
|
||||||
{{/required}}{{/allParams}}
|
{{/required}}{{/allParams}}
|
||||||
|
|
||||||
# resource path
|
# resource path
|
||||||
path = "{{path}}".sub('{format}','json'){{#pathParams}}.sub('{' + '{{baseName}}' + '}', {{paramName}}.to_s){{/pathParams}}
|
path = "{{path}}".sub('{format}','json'){{#pathParams}}.sub('{' + '{{baseName}}' + '}', {{paramName}}.to_s){{/pathParams}}
|
||||||
|
|
||||||
# query parameters
|
# query parameters
|
||||||
query_params = {}{{#queryParams}}{{#required}}
|
query_params = {}{{#queryParams}}{{#required}}
|
||||||
query_params[:'{{{baseName}}}'] = {{{paramName}}}{{/required}}{{/queryParams}}{{#queryParams}}{{^required}}
|
query_params[:'{{{baseName}}}'] = {{{paramName}}}{{/required}}{{/queryParams}}{{#queryParams}}{{^required}}
|
||||||
query_params[:'{{{baseName}}}'] = opts[:'{{{paramName}}}'] if opts[:'{{{paramName}}}']{{/required}}{{/queryParams}}
|
query_params[:'{{{baseName}}}'] = opts[:'{{{paramName}}}'] if opts[:'{{{paramName}}}']{{/required}}{{/queryParams}}
|
||||||
|
|
||||||
# header parameters
|
# header parameters
|
||||||
header_params = {}
|
header_params = {}
|
||||||
|
|
||||||
# HTTP header 'Accept' (if needed)
|
# HTTP header 'Accept' (if needed)
|
||||||
_header_accept = [{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]
|
_header_accept = [{{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]
|
||||||
_header_accept_result = Swagger::Request.select_header_accept(_header_accept) and header_params['Accept'] = _header_accept_result
|
_header_accept_result = Swagger::Request.select_header_accept(_header_accept) and header_params['Accept'] = _header_accept_result
|
||||||
|
|
||||||
# HTTP header 'Content-Type'
|
# HTTP header 'Content-Type'
|
||||||
_header_content_type = [{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]
|
_header_content_type = [{{#consumes}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]
|
||||||
header_params['Content-Type'] = Swagger::Request.select_header_content_type(_header_content_type){{#headerParams}}{{#required}}
|
header_params['Content-Type'] = Swagger::Request.select_header_content_type(_header_content_type){{#headerParams}}{{#required}}
|
||||||
header_params[:'{{{baseName}}}'] = {{{paramName}}}{{/required}}{{/headerParams}}{{#headerParams}}{{^required}}
|
header_params[:'{{{baseName}}}'] = {{{paramName}}}{{/required}}{{/headerParams}}{{#headerParams}}{{^required}}
|
||||||
header_params[:'{{{baseName}}}'] = opts[:'{{{paramName}}}'] if opts[:'{{{paramName}}}']{{/required}}{{/headerParams}}
|
header_params[:'{{{baseName}}}'] = opts[:'{{{paramName}}}'] if opts[:'{{{paramName}}}']{{/required}}{{/headerParams}}
|
||||||
|
|
||||||
# form parameters
|
# form parameters
|
||||||
form_params = {}{{#formParams}}{{#required}}
|
form_params = {}{{#formParams}}{{#required}}
|
||||||
form_params["{{baseName}}"] = {{paramName}}{{/required}}{{/formParams}}{{#formParams}}{{^required}}
|
form_params["{{baseName}}"] = {{paramName}}{{/required}}{{/formParams}}{{#formParams}}{{^required}}
|
||||||
form_params["{{baseName}}"] = opts[:'{{paramName}}'] if opts[:'{{paramName}}']{{/required}}{{/formParams}}
|
form_params["{{baseName}}"] = opts[:'{{paramName}}'] if opts[:'{{paramName}}']{{/required}}{{/formParams}}
|
||||||
|
|
||||||
# http body (model)
|
# http body (model)
|
||||||
{{^bodyParam}}post_body = nil
|
{{^bodyParam}}post_body = nil
|
||||||
{{/bodyParam}}{{#bodyParam}}post_body = Swagger::Request.object_to_http_body({{#required}}{{{paramName}}}{{/required}}{{^required}}opts[:'{{{paramName}}}']{{/required}})
|
{{/bodyParam}}{{#bodyParam}}post_body = Swagger::Request.object_to_http_body({{#required}}{{{paramName}}}{{/required}}{{^required}}opts[:'{{{paramName}}}']{{/required}})
|
||||||
{{/bodyParam}}
|
{{/bodyParam}}
|
||||||
|
|
||||||
{{#returnType}}response = Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body
|
{{#returnType}}response = Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params, :headers => header_params, :form_params => form_params, :body => post_body}).make.body
|
||||||
{{#returnContainer}}response.map {|response| {{/returnContainer}}obj = {{returnBaseType}}.new() and obj.build_from_hash(response){{#returnContainer}} }{{/returnContainer}}{{/returnType}}{{^returnType}} Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make{{/returnType}}
|
{{#returnContainer}}response.map {|response| {{/returnContainer}}obj = {{returnBaseType}}.new() and obj.build_from_hash(response){{#returnContainer}} }{{/returnContainer}}{{/returnType}}{{^returnType}} Swagger::Request.new(:{{httpMethod}}, path, {:params => query_params,:headers => header_params, :form_params => form_params, :body => post_body}).make{{/returnType}}
|
||||||
end
|
end
|
||||||
{{/operation}}
|
{{/operation}}
|
||||||
end
|
end
|
||||||
{{/operations}}
|
{{/operations}}
|
||||||
|
end
|
||||||
|
@ -1,83 +1,83 @@
|
|||||||
# base class containing fundamental method such as to_hash, build_from_hash and more
|
module {{moduleName}}
|
||||||
class BaseObject
|
# base class containing fundamental method such as to_hash, build_from_hash and more
|
||||||
|
class BaseObject
|
||||||
|
|
||||||
# return the object in the form of hash
|
# return the object in the form of hash
|
||||||
def to_body
|
def to_body
|
||||||
body = {}
|
body = {}
|
||||||
self.class.attribute_map.each_pair do |key, value|
|
self.class.attribute_map.each_pair do |key, value|
|
||||||
body[value] = self.send(key) unless self.send(key).nil?
|
body[value] = self.send(key) unless self.send(key).nil?
|
||||||
|
end
|
||||||
|
body
|
||||||
end
|
end
|
||||||
body
|
|
||||||
end
|
|
||||||
|
|
||||||
# build the object from hash
|
# build the object from hash
|
||||||
def build_from_hash(attributes)
|
def build_from_hash(attributes)
|
||||||
return nil unless attributes.is_a?(Hash)
|
return nil unless attributes.is_a?(Hash)
|
||||||
self.class.swagger_types.each_pair do |key, type|
|
self.class.swagger_types.each_pair do |key, type|
|
||||||
if type =~ /^array\[(.*)\]/i
|
if type =~ /^array\[(.*)\]/i
|
||||||
if attributes[self.class.attribute_map[key]].is_a?(Array)
|
if attributes[self.class.attribute_map[key]].is_a?(Array)
|
||||||
self.send("#{key}=", attributes[self.class.attribute_map[key]].map{ |v| _deserialize($1, v) } )
|
self.send("#{key}=", attributes[self.class.attribute_map[key]].map{ |v| _deserialize($1, v) } )
|
||||||
|
else
|
||||||
|
#TODO show warning in debug mode
|
||||||
|
end
|
||||||
|
elsif !attributes[self.class.attribute_map[key]].nil?
|
||||||
|
self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
|
||||||
else
|
else
|
||||||
#TODO show warning in debug mode
|
# data not found in attributes(hash), not an issue as the data can be optional
|
||||||
end
|
|
||||||
elsif !attributes[self.class.attribute_map[key]].nil?
|
|
||||||
self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
|
|
||||||
else
|
|
||||||
# data not found in attributes(hash), not an issue as the data can be optional
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
def _deserialize(type, value)
|
|
||||||
case type.to_sym
|
|
||||||
when :DateTime
|
|
||||||
DateTime.parse(value)
|
|
||||||
when :string
|
|
||||||
value.to_s
|
|
||||||
when :int
|
|
||||||
value.to_i
|
|
||||||
when :double
|
|
||||||
value.to_f
|
|
||||||
when :boolean
|
|
||||||
if value =~ /^(true|t|yes|y|1)$/i
|
|
||||||
true
|
|
||||||
else
|
|
||||||
false
|
|
||||||
end
|
|
||||||
else # model
|
|
||||||
_model = Object.const_get(type).new
|
|
||||||
_model.build_from_hash(value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# to_body is an alias to to_body (backward compatibility)
|
|
||||||
def to_hash
|
|
||||||
hash = {}
|
|
||||||
self.class.attribute_map.each_pair do |key, value|
|
|
||||||
if self.send(key).is_a?(Array)
|
|
||||||
next if self.send(key).empty?
|
|
||||||
hash[value] = self.send(key).select{|v| !v.nil?}.map{ |v| _to_hash v} unless self.send(key).nil?
|
|
||||||
else
|
|
||||||
unless (_tmp_value = _to_hash self.send(key)).nil?
|
|
||||||
hash[value] = _tmp_value
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
hash
|
|
||||||
end
|
|
||||||
|
|
||||||
# Method to output non-array value in the form of hash
|
self
|
||||||
# For object, use to_hash. Otherwise, just return the value
|
|
||||||
def _to_hash(value)
|
|
||||||
if value.respond_to? :to_hash
|
|
||||||
value.to_hash
|
|
||||||
else
|
|
||||||
value
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
def _deserialize(type, value)
|
||||||
|
case type.to_sym
|
||||||
|
when :DateTime
|
||||||
|
DateTime.parse(value)
|
||||||
|
when :string
|
||||||
|
value.to_s
|
||||||
|
when :int
|
||||||
|
value.to_i
|
||||||
|
when :double
|
||||||
|
value.to_f
|
||||||
|
when :boolean
|
||||||
|
if value =~ /^(true|t|yes|y|1)$/i
|
||||||
|
true
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
else # model
|
||||||
|
_model = {{moduleName}}.const_get(type).new
|
||||||
|
_model.build_from_hash(value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# to_body is an alias to to_body (backward compatibility)
|
||||||
|
def to_hash
|
||||||
|
hash = {}
|
||||||
|
self.class.attribute_map.each_pair do |key, value|
|
||||||
|
if self.send(key).is_a?(Array)
|
||||||
|
next if self.send(key).empty?
|
||||||
|
hash[value] = self.send(key).select{|v| !v.nil?}.map{ |v| _to_hash v} unless self.send(key).nil?
|
||||||
|
else
|
||||||
|
unless (_tmp_value = _to_hash self.send(key)).nil?
|
||||||
|
hash[value] = _tmp_value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
|
||||||
|
# Method to output non-array value in the form of hash
|
||||||
|
# For object, use to_hash. Otherwise, just return the value
|
||||||
|
def _to_hash(value)
|
||||||
|
if value.respond_to? :to_hash
|
||||||
|
value.to_hash
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,41 +1,40 @@
|
|||||||
require_relative 'base_object'
|
module {{moduleName}}
|
||||||
|
{{#models}} # {{description}}
|
||||||
{{#models}}#{{description}}
|
{{#model}} class {{classname}} < BaseObject
|
||||||
{{#model}}class {{classname}} < BaseObject
|
attr_accessor {{#vars}}:{{{name}}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{newline}}
|
||||||
attr_accessor {{#vars}}:{{{name}}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{newline}}
|
# attribute mapping from ruby-style variable name to JSON key
|
||||||
# attribute mapping from ruby-style variable name to JSON key
|
def self.attribute_map
|
||||||
def self.attribute_map
|
{
|
||||||
{
|
{{#vars}}
|
||||||
{{#vars}}
|
# {{description}}
|
||||||
# {{description}}
|
:'{{{name}}}' => :'{{{baseName}}}'{{#hasMore}},{{/hasMore}}
|
||||||
:'{{{name}}}' => :'{{{baseName}}}'{{#hasMore}},{{/hasMore}}
|
{{/vars}}
|
||||||
{{/vars}}
|
}
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
# attribute type
|
|
||||||
def self.swagger_types
|
|
||||||
{
|
|
||||||
{{#vars}}:'{{{name}}}' => :'{{{datatype}}}'{{#hasMore}},{{/hasMore}}
|
|
||||||
{{/vars}}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(attributes = {})
|
|
||||||
return if !attributes.is_a?(Hash) || attributes.empty?
|
|
||||||
|
|
||||||
# convert string to symbol for hash key
|
|
||||||
attributes = attributes.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
|
||||||
|
|
||||||
{{#vars}}
|
|
||||||
if attributes[:'{{{baseName}}}']
|
|
||||||
{{#isContainer}}if (value = attributes[:'{{{baseName}}}']).is_a?(Array)
|
|
||||||
@{{{name}}} = value
|
|
||||||
end{{/isContainer}}{{^isContainer}}@{{{name}}} = attributes[:'{{{baseName}}}']{{/isContainer}}
|
|
||||||
end
|
end
|
||||||
{{/vars}}
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
# attribute type
|
||||||
|
def self.swagger_types
|
||||||
|
{
|
||||||
|
{{#vars}}:'{{{name}}}' => :'{{{datatype}}}'{{#hasMore}},{{/hasMore}}
|
||||||
|
{{/vars}}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(attributes = {})
|
||||||
|
return if !attributes.is_a?(Hash) || attributes.empty?
|
||||||
|
|
||||||
|
# convert string to symbol for hash key
|
||||||
|
attributes = attributes.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
||||||
|
|
||||||
|
{{#vars}}
|
||||||
|
if attributes[:'{{{baseName}}}']
|
||||||
|
{{#isContainer}}if (value = attributes[:'{{{baseName}}}']).is_a?(Array)
|
||||||
|
@{{{name}}} = value
|
||||||
|
end{{/isContainer}}{{^isContainer}}@{{{name}}} = attributes[:'{{{baseName}}}']{{/isContainer}}
|
||||||
|
end
|
||||||
|
{{/vars}}
|
||||||
|
end
|
||||||
|
end
|
||||||
{{/model}}
|
{{/model}}
|
||||||
{{/models}}
|
{{/models}}
|
||||||
|
end
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
|
||||||
$:.push File.expand_path("../lib", __FILE__)
|
|
||||||
require "swagger/version"
|
|
||||||
|
|
||||||
Gem::Specification.new do |s|
|
|
||||||
s.name = "{{artifactId}}"
|
|
||||||
s.version = Swagger::VERSION
|
|
||||||
s.platform = Gem::Platform::RUBY
|
|
||||||
s.authors = ["Zeke Sikelianos", "Tony Tam"]
|
|
||||||
s.email = ["zeke@wordnik.com", "tony@wordnik.com"]
|
|
||||||
s.homepage = "http://developer.wordnik.com"
|
|
||||||
s.summary = %q{A ruby wrapper for the swagger APIs}
|
|
||||||
s.description = %q{This gem maps to a swagger API}
|
|
||||||
|
|
||||||
s.rubyforge_project = "{{artifactId}}"
|
|
||||||
|
|
||||||
s.add_dependency 'typhoeus', '>=0.2.1'
|
|
||||||
s.add_dependency 'addressable', '>=2.2.4'
|
|
||||||
s.add_dependency 'json', '>=1.4.6'
|
|
||||||
|
|
||||||
s.add_development_dependency 'rspec', '>=2.5.0'
|
|
||||||
s.add_development_dependency 'vcr', '>=1.5.1'
|
|
||||||
s.add_development_dependency 'webmock', '>=1.6.2'
|
|
||||||
s.add_development_dependency 'autotest'
|
|
||||||
s.add_development_dependency 'autotest-rails-pure'
|
|
||||||
s.add_development_dependency 'autotest-growl'
|
|
||||||
s.add_development_dependency 'autotest-fsevent'
|
|
||||||
|
|
||||||
s.files = `find *`.split("\n").uniq.sort.select{|f| !f.empty? }
|
|
||||||
s.test_files = `find spec/*`.split("\n")
|
|
||||||
s.executables = []
|
|
||||||
s.require_paths = ["lib"]
|
|
||||||
end
|
|
@ -1,5 +0,0 @@
|
|||||||
require 'monkey'
|
|
||||||
require 'swagger'
|
|
||||||
|
|
||||||
Dir[File.join(File.dirname(__FILE__), "../lib/*.rb")].each {|file| require file if file !~ /swagger-client\.rb\z/ }
|
|
||||||
Dir[File.join(File.dirname(__FILE__), "../models/*.rb")].each {|file| require file }
|
|
@ -1,86 +1,78 @@
|
|||||||
require 'monkey'
|
|
||||||
require 'swagger/configuration'
|
|
||||||
require 'swagger/request'
|
|
||||||
require 'swagger/response'
|
|
||||||
require 'swagger/version'
|
|
||||||
require 'logger'
|
require 'logger'
|
||||||
require 'json'
|
require 'json'
|
||||||
|
|
||||||
module Swagger
|
module {{moduleName}}
|
||||||
|
module Swagger
|
||||||
@configuration = Configuration.new
|
class << self
|
||||||
|
attr_accessor :logger
|
||||||
|
|
||||||
class << self
|
# A Swagger configuration object. Must act like a hash and return sensible
|
||||||
attr_accessor :logger
|
# values for all Swagger configuration options. See Swagger::Configuration.
|
||||||
|
attr_accessor :configuration
|
||||||
# A Swagger configuration object. Must act like a hash and return sensible
|
|
||||||
# values for all Swagger configuration options. See Swagger::Configuration.
|
|
||||||
attr_accessor :configuration
|
|
||||||
|
|
||||||
attr_accessor :resources
|
attr_accessor :resources
|
||||||
|
|
||||||
# Call this method to modify defaults in your initializers.
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
# Swagger.configure do |config|
|
|
||||||
# config.api_key = '1234567890abcdef' # required
|
|
||||||
# config.username = 'wordlover' # optional, but needed for user-related functions
|
|
||||||
# config.password = 'i<3words' # optional, but needed for user-related functions
|
|
||||||
# config.format = 'json' # optional, defaults to 'json'
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
def configure
|
|
||||||
yield(configuration) if block_given?
|
|
||||||
|
|
||||||
# Configure logger. Default to use Rails
|
# Call this method to modify defaults in your initializers.
|
||||||
self.logger ||= configuration.logger || (defined?(Rails) ? Rails.logger : Logger.new(STDOUT))
|
#
|
||||||
|
# @example
|
||||||
|
# Swagger.configure do |config|
|
||||||
|
# config.api_key = '1234567890abcdef' # required
|
||||||
|
# config.username = 'wordlover' # optional, but needed for user-related functions
|
||||||
|
# config.password = 'i<3words' # optional, but needed for user-related functions
|
||||||
|
# config.format = 'json' # optional, defaults to 'json'
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
def configure
|
||||||
|
yield(configuration) if block_given?
|
||||||
|
|
||||||
# remove :// from scheme
|
# Configure logger. Default to use Rails
|
||||||
configuration.scheme.sub!(/:\/\//, '')
|
self.logger ||= configuration.logger || (defined?(Rails) ? Rails.logger : Logger.new(STDOUT))
|
||||||
|
|
||||||
# remove http(s):// and anything after a slash
|
# remove :// from scheme
|
||||||
configuration.host.sub!(/https?:\/\//, '')
|
configuration.scheme.sub!(/:\/\//, '')
|
||||||
configuration.host = configuration.host.split('/').first
|
|
||||||
|
|
||||||
# Add leading and trailing slashes to base_path
|
# remove http(s):// and anything after a slash
|
||||||
configuration.base_path = "/#{configuration.base_path}".gsub(/\/+/, '/')
|
configuration.host.sub!(/https?:\/\//, '')
|
||||||
configuration.base_path = "" if configuration.base_path == "/"
|
configuration.host = configuration.host.split('/').first
|
||||||
end
|
|
||||||
|
# Add leading and trailing slashes to base_path
|
||||||
def authenticated?
|
configuration.base_path = "/#{configuration.base_path}".gsub(/\/+/, '/')
|
||||||
Swagger.configuration.auth_token.present?
|
configuration.base_path = "" if configuration.base_path == "/"
|
||||||
end
|
end
|
||||||
|
|
||||||
def de_authenticate
|
def authenticated?
|
||||||
Swagger.configuration.auth_token = nil
|
Swagger.configuration.auth_token.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def authenticate
|
def de_authenticate
|
||||||
return if Swagger.authenticated?
|
Swagger.configuration.auth_token = nil
|
||||||
|
end
|
||||||
if Swagger.configuration.username.blank? || Swagger.configuration.password.blank?
|
|
||||||
raise ClientError, "Username and password are required to authenticate."
|
def authenticate
|
||||||
|
return if Swagger.authenticated?
|
||||||
|
|
||||||
|
if Swagger.configuration.username.blank? || Swagger.configuration.password.blank?
|
||||||
|
raise ClientError, "Username and password are required to authenticate."
|
||||||
|
end
|
||||||
|
|
||||||
|
request = Swagger::Request.new(
|
||||||
|
:get,
|
||||||
|
"account/authenticate/{username}",
|
||||||
|
:params => {
|
||||||
|
:username => Swagger.configuration.username,
|
||||||
|
:password => Swagger.configuration.password
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
response_body = request.response.body
|
||||||
|
Swagger.configuration.auth_token = response_body['token']
|
||||||
end
|
end
|
||||||
|
|
||||||
request = Swagger::Request.new(
|
|
||||||
:get,
|
|
||||||
"account/authenticate/{username}",
|
|
||||||
:params => {
|
|
||||||
:username => Swagger.configuration.username,
|
|
||||||
:password => Swagger.configuration.password
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
response_body = request.response.body
|
|
||||||
Swagger.configuration.auth_token = response_body['token']
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class ServerError < StandardError
|
class ServerError < StandardError
|
||||||
end
|
end
|
||||||
|
|
||||||
class ClientError < StandardError
|
class ClientError < StandardError
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,22 +1,19 @@
|
|||||||
module Swagger
|
module {{moduleName}}
|
||||||
|
module Swagger
|
||||||
class Configuration
|
class Configuration
|
||||||
require 'swagger/version'
|
attr_accessor :format, :api_key, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent
|
||||||
|
|
||||||
attr_accessor :format, :api_key, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent
|
# Defaults go in here..
|
||||||
|
def initialize
|
||||||
# Defaults go in here..
|
@format = 'json'
|
||||||
def initialize
|
@scheme = '{{scheme}}'
|
||||||
@format = 'json'
|
@host = '{{host}}'
|
||||||
@scheme = '{{scheme}}'
|
@base_path = '{{contextPath}}'
|
||||||
@host = '{{host}}'
|
@user_agent = "ruby-swagger-#{Swagger::VERSION}"
|
||||||
@base_path = '{{contextPath}}'
|
@inject_format = false
|
||||||
@user_agent = "ruby-swagger-#{Swagger::VERSION}"
|
@force_ending_format = false
|
||||||
@inject_format = false
|
@camelize_params = true
|
||||||
@force_ending_format = false
|
end
|
||||||
@camelize_params = true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1,263 +1,257 @@
|
|||||||
module Swagger
|
module {{moduleName}}
|
||||||
|
module Swagger
|
||||||
|
class Request
|
||||||
|
require 'uri'
|
||||||
|
require 'addressable/uri'
|
||||||
|
require 'typhoeus'
|
||||||
|
|
||||||
class Request
|
attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params
|
||||||
require 'uri'
|
|
||||||
require 'addressable/uri'
|
|
||||||
require 'typhoeus'
|
|
||||||
require "swagger/version"
|
|
||||||
|
|
||||||
attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params
|
# All requests must have an HTTP method and a path
|
||||||
|
# Optionals parameters are :params, :headers, :body, :format, :host
|
||||||
|
def initialize(http_method, path, attributes={})
|
||||||
|
attributes[:format] ||= Swagger.configuration.format
|
||||||
|
attributes[:params] ||= {}
|
||||||
|
|
||||||
|
# Set default headers
|
||||||
|
default_headers = {
|
||||||
|
'Content-Type' => "application/#{attributes[:format].downcase}",
|
||||||
|
:api_key => Swagger.configuration.api_key,
|
||||||
|
'User-Agent' => Swagger.configuration.user_agent
|
||||||
|
}
|
||||||
|
|
||||||
# All requests must have an HTTP method and a path
|
# api_key from headers hash trumps the default, even if its value is blank
|
||||||
# Optionals parameters are :params, :headers, :body, :format, :host
|
if attributes[:headers].present? && attributes[:headers].has_key?(:api_key)
|
||||||
#
|
default_headers.delete(:api_key)
|
||||||
def initialize(http_method, path, attributes={})
|
end
|
||||||
attributes[:format] ||= Swagger.configuration.format
|
|
||||||
attributes[:params] ||= {}
|
|
||||||
|
|
||||||
# Set default headers
|
# api_key from params hash trumps all others (headers and default_headers)
|
||||||
default_headers = {
|
if attributes[:params].present? && attributes[:params].has_key?(:api_key)
|
||||||
'Content-Type' => "application/#{attributes[:format].downcase}",
|
default_headers.delete(:api_key)
|
||||||
:api_key => Swagger.configuration.api_key,
|
attributes[:headers].delete(:api_key) if attributes[:headers].present?
|
||||||
'User-Agent' => Swagger.configuration.user_agent
|
end
|
||||||
}
|
|
||||||
|
|
||||||
# api_key from headers hash trumps the default, even if its value is blank
|
# Merge argument headers into defaults
|
||||||
if attributes[:headers].present? && attributes[:headers].has_key?(:api_key)
|
attributes[:headers] = default_headers.merge(attributes[:headers] || {})
|
||||||
default_headers.delete(:api_key)
|
|
||||||
end
|
|
||||||
|
|
||||||
# api_key from params hash trumps all others (headers and default_headers)
|
|
||||||
if attributes[:params].present? && attributes[:params].has_key?(:api_key)
|
|
||||||
default_headers.delete(:api_key)
|
|
||||||
attributes[:headers].delete(:api_key) if attributes[:headers].present?
|
|
||||||
end
|
|
||||||
|
|
||||||
# Merge argument headers into defaults
|
|
||||||
attributes[:headers] = default_headers.merge(attributes[:headers] || {})
|
|
||||||
|
|
||||||
# Stick in the auth token if there is one
|
|
||||||
if Swagger.authenticated?
|
|
||||||
attributes[:headers].merge!({:auth_token => Swagger.configuration.auth_token})
|
|
||||||
end
|
|
||||||
|
|
||||||
self.http_method = http_method.to_sym
|
|
||||||
self.path = path
|
|
||||||
attributes.each do |name, value|
|
|
||||||
send("#{name.to_s.underscore.to_sym}=", value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Construct a base URL
|
# Stick in the auth token if there is one
|
||||||
#
|
if Swagger.authenticated?
|
||||||
def url(options = {})
|
attributes[:headers].merge!({:auth_token => Swagger.configuration.auth_token})
|
||||||
u = Addressable::URI.new(
|
end
|
||||||
:scheme => Swagger.configuration.scheme,
|
|
||||||
:host => Swagger.configuration.host,
|
|
||||||
:path => self.interpreted_path,
|
|
||||||
:query => self.query_string.sub(/\?/, '')
|
|
||||||
).to_s
|
|
||||||
|
|
||||||
# Drop trailing question mark, if present
|
|
||||||
u.sub! /\?$/, ''
|
|
||||||
|
|
||||||
# Obfuscate API key?
|
|
||||||
u.sub! /api\_key=\w+/, 'api_key=YOUR_API_KEY' if options[:obfuscated]
|
|
||||||
|
|
||||||
u
|
|
||||||
end
|
|
||||||
|
|
||||||
# Iterate over the params hash, injecting any path values into the path string
|
self.http_method = http_method.to_sym
|
||||||
#
|
self.path = path
|
||||||
# e.g. /word.{format}/{word}/entries => /word.json/cat/entries
|
attributes.each do |name, value|
|
||||||
def interpreted_path
|
send("#{name.to_s.underscore.to_sym}=", value)
|
||||||
p = self.path.dup
|
|
||||||
|
|
||||||
# Stick a .{format} placeholder into the path if there isn't
|
|
||||||
# one already or an actual format like json or xml
|
|
||||||
# e.g. /words/blah => /words.{format}/blah
|
|
||||||
if Swagger.configuration.inject_format
|
|
||||||
unless ['.json', '.xml', '{format}'].any? {|s| p.downcase.include? s }
|
|
||||||
p = p.sub(/^(\/?\w+)/, "\\1.#{format}")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Stick a .{format} placeholder on the end of the path if there isn't
|
# Construct a base URL
|
||||||
# one already or an actual format like json or xml
|
def url(options = {})
|
||||||
# e.g. /words/blah => /words/blah.{format}
|
u = Addressable::URI.new(
|
||||||
if Swagger.configuration.force_ending_format
|
:scheme => Swagger.configuration.scheme,
|
||||||
unless ['.json', '.xml', '{format}'].any? {|s| p.downcase.include? s }
|
:host => Swagger.configuration.host,
|
||||||
p = "#{p}.#{format}"
|
:path => self.interpreted_path,
|
||||||
|
:query => self.query_string.sub(/\?/, '')
|
||||||
|
).to_s
|
||||||
|
|
||||||
|
# Drop trailing question mark, if present
|
||||||
|
u.sub! /\?$/, ''
|
||||||
|
|
||||||
|
# Obfuscate API key?
|
||||||
|
u.sub! /api\_key=\w+/, 'api_key=YOUR_API_KEY' if options[:obfuscated]
|
||||||
|
|
||||||
|
u
|
||||||
|
end
|
||||||
|
|
||||||
|
# Iterate over the params hash, injecting any path values into the path string
|
||||||
|
# e.g. /word.{format}/{word}/entries => /word.json/cat/entries
|
||||||
|
def interpreted_path
|
||||||
|
p = self.path.dup
|
||||||
|
|
||||||
|
# Stick a .{format} placeholder into the path if there isn't
|
||||||
|
# one already or an actual format like json or xml
|
||||||
|
# e.g. /words/blah => /words.{format}/blah
|
||||||
|
if Swagger.configuration.inject_format
|
||||||
|
unless ['.json', '.xml', '{format}'].any? {|s| p.downcase.include? s }
|
||||||
|
p = p.sub(/^(\/?\w+)/, "\\1.#{format}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Stick a .{format} placeholder on the end of the path if there isn't
|
||||||
|
# one already or an actual format like json or xml
|
||||||
|
# e.g. /words/blah => /words/blah.{format}
|
||||||
|
if Swagger.configuration.force_ending_format
|
||||||
|
unless ['.json', '.xml', '{format}'].any? {|s| p.downcase.include? s }
|
||||||
|
p = "#{p}.#{format}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
p = p.sub("{format}", self.format.to_s)
|
||||||
|
|
||||||
|
URI.encode [Swagger.configuration.base_path, p].join("/").gsub(/\/+/, '/')
|
||||||
|
end
|
||||||
|
|
||||||
|
# Massage the request body into a state of readiness
|
||||||
|
# If body is a hash, camelize all keys then convert to a json string
|
||||||
|
def body=(value)
|
||||||
|
if value.is_a?(Hash)
|
||||||
|
value = value.inject({}) do |memo, (k,v)|
|
||||||
|
memo[k.to_s.camelize(:lower).to_sym] = v
|
||||||
|
memo
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@body = value
|
||||||
|
end
|
||||||
|
|
||||||
|
# If body is an object, JSONify it before making the actual request.
|
||||||
|
# For form parameters, remove empty value
|
||||||
|
def outgoing_body
|
||||||
|
# http form
|
||||||
|
if @body.nil? && @form_params && !@form_params.empty?
|
||||||
|
data = form_params.dup
|
||||||
|
data.each do |key, value|
|
||||||
|
data[key] = value.to_s if value && !value.is_a?(File) # remove emtpy form parameter
|
||||||
|
end
|
||||||
|
data
|
||||||
|
else # http body is JSON
|
||||||
|
@body.is_a?(String) ? @body : @body.to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
p = p.sub("{format}", self.format.to_s)
|
# Construct a query string from the query-string-type params
|
||||||
|
def query_string
|
||||||
URI.encode [Swagger.configuration.base_path, p].join("/").gsub(/\/+/, '/')
|
# Iterate over all params,
|
||||||
end
|
# .. removing the ones that are part of the path itself.
|
||||||
|
# .. stringifying values so Addressable doesn't blow up.
|
||||||
# Massage the request body into a state of readiness
|
query_values = {}
|
||||||
# If body is a hash, camelize all keys then convert to a json string
|
self.params.each_pair do |key, value|
|
||||||
#
|
next if self.path.include? "{#{key}}" # skip path params
|
||||||
def body=(value)
|
next if value.blank? && value.class != FalseClass # skip empties
|
||||||
if value.is_a?(Hash)
|
if Swagger.configuration.camelize_params
|
||||||
value = value.inject({}) do |memo, (k,v)|
|
key = key.to_s.camelize(:lower).to_sym unless key.to_sym == :api_key # api_key is not a camelCased param
|
||||||
memo[k.to_s.camelize(:lower).to_sym] = v
|
end
|
||||||
memo
|
query_values[key] = value.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
# We don't want to end up with '?' as our query string
|
||||||
|
# if there aren't really any params
|
||||||
|
return "" if query_values.blank?
|
||||||
|
|
||||||
|
# Addressable requires query_values to be set after initialization..
|
||||||
|
qs = Addressable::URI.new
|
||||||
|
qs.query_values = query_values
|
||||||
|
qs.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def make
|
||||||
|
#TODO use configuration setting to determine if debugging
|
||||||
|
#logger = Logger.new STDOUT
|
||||||
|
#logger.debug self.url
|
||||||
|
response = case self.http_method.to_sym
|
||||||
|
when :get,:GET
|
||||||
|
Typhoeus::Request.get(
|
||||||
|
self.url,
|
||||||
|
:headers => self.headers.stringify_keys,
|
||||||
|
)
|
||||||
|
|
||||||
|
when :post,:POST
|
||||||
|
Typhoeus::Request.post(
|
||||||
|
self.url,
|
||||||
|
:body => self.outgoing_body,
|
||||||
|
:headers => self.headers.stringify_keys,
|
||||||
|
)
|
||||||
|
|
||||||
|
when :patch,:PATCH
|
||||||
|
Typhoeus::Request.patch(
|
||||||
|
self.url,
|
||||||
|
:body => self.outgoing_body,
|
||||||
|
:headers => self.headers.stringify_keys,
|
||||||
|
)
|
||||||
|
|
||||||
|
when :put,:PUT
|
||||||
|
Typhoeus::Request.put(
|
||||||
|
self.url,
|
||||||
|
:body => self.outgoing_body,
|
||||||
|
:headers => self.headers.stringify_keys,
|
||||||
|
)
|
||||||
|
|
||||||
|
when :delete,:DELETE
|
||||||
|
Typhoeus::Request.delete(
|
||||||
|
self.url,
|
||||||
|
:body => self.outgoing_body,
|
||||||
|
:headers => self.headers.stringify_keys,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
Response.new(response)
|
||||||
|
end
|
||||||
|
|
||||||
|
def response
|
||||||
|
self.make
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_code_pretty
|
||||||
|
return unless @response.present?
|
||||||
|
@response.code.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_headers_pretty
|
||||||
|
return unless @response.present?
|
||||||
|
# JSON.pretty_generate(@response.headers).gsub(/\n/, '<br/>') # <- This was for RestClient
|
||||||
|
@response.headers.gsub(/\n/, '<br/>') # <- This is for Typhoeus
|
||||||
|
end
|
||||||
|
|
||||||
|
# return 'Accept' based on an array of accept provided
|
||||||
|
# @param [Array] header_accept_array Array fo 'Accept'
|
||||||
|
# @return String Accept (e.g. application/json)
|
||||||
|
def self.select_header_accept header_accept_array
|
||||||
|
if header_accept_array.empty?
|
||||||
|
return
|
||||||
|
elsif header_accept_array.any?{ |s| s.casecmp('application/json')==0 }
|
||||||
|
'application/json' # look for json data by default
|
||||||
|
else
|
||||||
|
header_accept_array.join(',')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@body = value
|
|
||||||
end
|
# return the content type based on an array of content-type provided
|
||||||
|
# @param [Array] content_type_array Array fo content-type
|
||||||
# If body is an object, JSONify it before making the actual request.
|
# @return String Content-Type (e.g. application/json)
|
||||||
# For form parameters, remove empty value
|
def self.select_header_content_type content_type_array
|
||||||
def outgoing_body
|
if content_type_array.empty?
|
||||||
# http form
|
'application/json' # use application/json by default
|
||||||
if @body.nil? && @form_params && !@form_params.empty?
|
elsif content_type_array.any?{ |s| s.casecmp('application/json')==0 }
|
||||||
data = form_params.dup
|
'application/json' # use application/json if it's included
|
||||||
data.each do |key, value|
|
else
|
||||||
data[key] = value.to_s if value && !value.is_a?(File) # remove emtpy form parameter
|
content_type_array[0]; # otherwise, use the first one
|
||||||
end
|
end
|
||||||
data
|
|
||||||
else # http body is JSON
|
|
||||||
@body.is_a?(String) ? @body : @body.to_json
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# Construct a query string from the query-string-type params
|
|
||||||
def query_string
|
|
||||||
|
|
||||||
# Iterate over all params,
|
# static method to convert object (array, hash, object, etc) to JSON string
|
||||||
# .. removing the ones that are part of the path itself.
|
# @param model object to be converted into JSON string
|
||||||
# .. stringifying values so Addressable doesn't blow up.
|
# @return string JSON string representation of the object
|
||||||
query_values = {}
|
def self.object_to_http_body model
|
||||||
self.params.each_pair do |key, value|
|
return if model.nil?
|
||||||
next if self.path.include? "{#{key}}" # skip path params
|
_body = nil
|
||||||
next if value.blank? && value.class != FalseClass # skip empties
|
if model.is_a?(Array)
|
||||||
if Swagger.configuration.camelize_params
|
_body = model.map{|m| object_to_hash(m) }
|
||||||
key = key.to_s.camelize(:lower).to_sym unless key.to_sym == :api_key # api_key is not a camelCased param
|
else
|
||||||
|
_body = object_to_hash(model)
|
||||||
end
|
end
|
||||||
query_values[key] = value.to_s
|
_body.to_json
|
||||||
end
|
end
|
||||||
|
|
||||||
# We don't want to end up with '?' as our query string
|
|
||||||
# if there aren't really any params
|
|
||||||
return "" if query_values.blank?
|
|
||||||
|
|
||||||
# Addressable requires query_values to be set after initialization..
|
|
||||||
qs = Addressable::URI.new
|
|
||||||
qs.query_values = query_values
|
|
||||||
qs.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def make
|
|
||||||
#TODO use configuration setting to determine if debugging
|
|
||||||
#logger = Logger.new STDOUT
|
|
||||||
#logger.debug self.url
|
|
||||||
response = case self.http_method.to_sym
|
|
||||||
when :get,:GET
|
|
||||||
Typhoeus::Request.get(
|
|
||||||
self.url,
|
|
||||||
:headers => self.headers.stringify_keys,
|
|
||||||
)
|
|
||||||
|
|
||||||
when :post,:POST
|
# static method to convert object(non-array) to hash
|
||||||
Typhoeus::Request.post(
|
# @param obj object to be converted into JSON string
|
||||||
self.url,
|
# @return string JSON string representation of the object
|
||||||
:body => self.outgoing_body,
|
def self.object_to_hash obj
|
||||||
:headers => self.headers.stringify_keys,
|
if obj.respond_to?(:to_hash)
|
||||||
)
|
obj.to_hash
|
||||||
|
else
|
||||||
when :patch,:PATCH
|
obj
|
||||||
Typhoeus::Request.patch(
|
end
|
||||||
self.url,
|
|
||||||
:body => self.outgoing_body,
|
|
||||||
:headers => self.headers.stringify_keys,
|
|
||||||
)
|
|
||||||
|
|
||||||
when :put,:PUT
|
|
||||||
Typhoeus::Request.put(
|
|
||||||
self.url,
|
|
||||||
:body => self.outgoing_body,
|
|
||||||
:headers => self.headers.stringify_keys,
|
|
||||||
)
|
|
||||||
|
|
||||||
when :delete,:DELETE
|
|
||||||
Typhoeus::Request.delete(
|
|
||||||
self.url,
|
|
||||||
:body => self.outgoing_body,
|
|
||||||
:headers => self.headers.stringify_keys,
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
Response.new(response)
|
|
||||||
end
|
|
||||||
|
|
||||||
def response
|
|
||||||
self.make
|
|
||||||
end
|
|
||||||
|
|
||||||
def response_code_pretty
|
|
||||||
return unless @response.present?
|
|
||||||
@response.code.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def response_headers_pretty
|
|
||||||
return unless @response.present?
|
|
||||||
# JSON.pretty_generate(@response.headers).gsub(/\n/, '<br/>') # <- This was for RestClient
|
|
||||||
@response.headers.gsub(/\n/, '<br/>') # <- This is for Typhoeus
|
|
||||||
end
|
|
||||||
|
|
||||||
# return 'Accept' based on an array of accept provided
|
|
||||||
# @param [Array] header_accept_array Array fo 'Accept'
|
|
||||||
# @return String Accept (e.g. application/json)
|
|
||||||
def self.select_header_accept header_accept_array
|
|
||||||
if header_accept_array.empty?
|
|
||||||
return
|
|
||||||
elsif header_accept_array.any?{ |s| s.casecmp('application/json')==0 }
|
|
||||||
'application/json' # look for json data by default
|
|
||||||
else
|
|
||||||
header_accept_array.join(',')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# return the content type based on an array of content-type provided
|
|
||||||
# @param [Array] content_type_array Array fo content-type
|
|
||||||
# @return String Content-Type (e.g. application/json)
|
|
||||||
def self.select_header_content_type content_type_array
|
|
||||||
if content_type_array.empty?
|
|
||||||
'application/json' # use application/json by default
|
|
||||||
elsif content_type_array.any?{ |s| s.casecmp('application/json')==0 }
|
|
||||||
'application/json' # use application/json if it's included
|
|
||||||
else
|
|
||||||
content_type_array[0]; # otherwise, use the first one
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# static method to convert object (array, hash, object, etc) to JSON string
|
|
||||||
# @param model object to be converted into JSON string
|
|
||||||
# @return string JSON string representation of the object
|
|
||||||
def self.object_to_http_body model
|
|
||||||
return if model.nil?
|
|
||||||
_body = nil
|
|
||||||
if model.is_a?(Array)
|
|
||||||
_body = model.map{|m| object_to_hash(m) }
|
|
||||||
else
|
|
||||||
_body = object_to_hash(model)
|
|
||||||
end
|
|
||||||
_body.to_json
|
|
||||||
end
|
|
||||||
|
|
||||||
# static method to convert object(non-array) to hash
|
|
||||||
# @param obj object to be converted into JSON string
|
|
||||||
# @return string JSON string representation of the object
|
|
||||||
def self.object_to_hash obj
|
|
||||||
if obj.respond_to?(:to_hash)
|
|
||||||
obj.to_hash
|
|
||||||
else
|
|
||||||
obj
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,70 +1,70 @@
|
|||||||
module Swagger
|
module {{moduleName}}
|
||||||
|
module Swagger
|
||||||
|
class Response
|
||||||
|
require 'json'
|
||||||
|
|
||||||
class Response
|
attr_accessor :raw
|
||||||
require 'json'
|
|
||||||
|
|
||||||
attr_accessor :raw
|
def initialize(raw)
|
||||||
|
self.raw = raw
|
||||||
|
|
||||||
def initialize(raw)
|
case self.code
|
||||||
self.raw = raw
|
when 500..510 then raise(ServerError, self.error_message)
|
||||||
|
when 299..426 then raise(ClientError, self.error_message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
case self.code
|
def code
|
||||||
when 500..510 then raise(ServerError, self.error_message)
|
raw.code
|
||||||
when 299..426 then raise(ClientError, self.error_message)
|
end
|
||||||
|
|
||||||
|
# Account for error messages that take different forms...
|
||||||
|
def error_message
|
||||||
|
body['message']
|
||||||
|
rescue
|
||||||
|
body
|
||||||
|
end
|
||||||
|
|
||||||
|
# If body is JSON, parse it
|
||||||
|
# Otherwise return raw string
|
||||||
|
def body
|
||||||
|
JSON.parse(raw.body, :symbolize_names => true)
|
||||||
|
rescue
|
||||||
|
raw.body
|
||||||
|
end
|
||||||
|
|
||||||
|
# `headers_hash` is a Typhoeus-specific extension of Hash,
|
||||||
|
# so simplify it back into a regular old Hash.
|
||||||
|
def headers
|
||||||
|
h = {}
|
||||||
|
raw.headers_hash.each {|k,v| h[k] = v }
|
||||||
|
h
|
||||||
|
end
|
||||||
|
|
||||||
|
# Extract the response format from the header hash
|
||||||
|
# e.g. {'Content-Type' => 'application/json'}
|
||||||
|
def format
|
||||||
|
headers['Content-Type'].split("/").last.downcase
|
||||||
|
end
|
||||||
|
|
||||||
|
def json?
|
||||||
|
format == 'json'
|
||||||
|
end
|
||||||
|
|
||||||
|
def xml?
|
||||||
|
format == 'xml'
|
||||||
|
end
|
||||||
|
|
||||||
|
def pretty_body
|
||||||
|
return unless body.present?
|
||||||
|
case format
|
||||||
|
when 'json' then JSON.pretty_generate(body).gsub(/\n/, '<br/>')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pretty_headers
|
||||||
|
JSON.pretty_generate(headers).gsub(/\n/, '<br/>')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def code
|
|
||||||
raw.code
|
|
||||||
end
|
|
||||||
|
|
||||||
# Account for error messages that take different forms...
|
|
||||||
def error_message
|
|
||||||
body['message']
|
|
||||||
rescue
|
|
||||||
body
|
|
||||||
end
|
|
||||||
|
|
||||||
# If body is JSON, parse it
|
|
||||||
# Otherwise return raw string
|
|
||||||
def body
|
|
||||||
JSON.parse(raw.body, :symbolize_names => true)
|
|
||||||
rescue
|
|
||||||
raw.body
|
|
||||||
end
|
|
||||||
|
|
||||||
# `headers_hash` is a Typhoeus-specific extension of Hash,
|
|
||||||
# so simplify it back into a regular old Hash.
|
|
||||||
def headers
|
|
||||||
h = {}
|
|
||||||
raw.headers_hash.each {|k,v| h[k] = v }
|
|
||||||
h
|
|
||||||
end
|
|
||||||
|
|
||||||
# Extract the response format from the header hash
|
|
||||||
# e.g. {'Content-Type' => 'application/json'}
|
|
||||||
def format
|
|
||||||
headers['Content-Type'].split("/").last.downcase
|
|
||||||
end
|
|
||||||
|
|
||||||
def json?
|
|
||||||
format == 'json'
|
|
||||||
end
|
|
||||||
|
|
||||||
def xml?
|
|
||||||
format == 'xml'
|
|
||||||
end
|
|
||||||
|
|
||||||
def pretty_body
|
|
||||||
return unless body.present?
|
|
||||||
case format
|
|
||||||
when 'json' then JSON.pretty_generate(body).gsub(/\n/, '<br/>')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def pretty_headers
|
|
||||||
JSON.pretty_generate(headers).gsub(/\n/, '<br/>')
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
module Swagger
|
module {{moduleName}}
|
||||||
VERSION = "4.06.08"
|
module Swagger
|
||||||
|
VERSION = "{{appVersion}}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
$:.push File.expand_path("../lib", __FILE__)
|
||||||
|
require "{{gemName}}/swagger/version"
|
||||||
|
|
||||||
|
Gem::Specification.new do |s|
|
||||||
|
s.name = "{{gemName}}"
|
||||||
|
s.version = {{moduleName}}::Swagger::VERSION
|
||||||
|
s.platform = Gem::Platform::RUBY
|
||||||
|
s.authors = ["Zeke Sikelianos", "Tony Tam"]
|
||||||
|
s.email = ["zeke@wordnik.com", "tony@wordnik.com"]
|
||||||
|
s.homepage = "http://developer.wordnik.com"
|
||||||
|
s.summary = %q{A ruby wrapper for the swagger APIs}
|
||||||
|
s.description = %q{This gem maps to a swagger API}
|
||||||
|
s.license = "Apache-2.0"
|
||||||
|
|
||||||
|
s.add_runtime_dependency 'typhoeus', '~> 0.2', '>= 0.2.1'
|
||||||
|
s.add_runtime_dependency 'addressable', '~> 2.2', '>= 2.2.4'
|
||||||
|
s.add_runtime_dependency 'json', '~> 1.4', '>= 1.4.6'
|
||||||
|
|
||||||
|
s.add_development_dependency 'rspec', '~> 3.2', '>= 3.2.0'
|
||||||
|
s.add_development_dependency 'vcr', '~> 2.9', '>= 2.9.3'
|
||||||
|
s.add_development_dependency 'webmock', '~> 1.6', '>= 1.6.2'
|
||||||
|
s.add_development_dependency 'autotest', '~> 4.4', '>= 4.4.6'
|
||||||
|
s.add_development_dependency 'autotest-rails-pure', '~> 4.1', '>= 4.1.2'
|
||||||
|
s.add_development_dependency 'autotest-growl', '~> 0.2', '>= 0.2.16'
|
||||||
|
s.add_development_dependency 'autotest-fsevent', '~> 0.2', '>= 0.2.10'
|
||||||
|
|
||||||
|
s.files = `find *`.split("\n").uniq.sort.select{|f| !f.empty? }
|
||||||
|
s.test_files = `find spec/*`.split("\n")
|
||||||
|
s.executables = []
|
||||||
|
s.require_paths = ["lib"]
|
||||||
|
end
|
@ -0,0 +1,25 @@
|
|||||||
|
# Swagger common files
|
||||||
|
require '{{gemName}}/monkey'
|
||||||
|
require '{{gemName}}/swagger'
|
||||||
|
require '{{gemName}}/swagger/configuration'
|
||||||
|
require '{{gemName}}/swagger/request'
|
||||||
|
require '{{gemName}}/swagger/response'
|
||||||
|
require '{{gemName}}/swagger/version'
|
||||||
|
|
||||||
|
# Models
|
||||||
|
require '{{modelPackage}}/base_object'
|
||||||
|
{{#models}}
|
||||||
|
require '{{importPath}}'
|
||||||
|
{{/models}}
|
||||||
|
|
||||||
|
# APIs
|
||||||
|
{{#apiInfo}}
|
||||||
|
{{#apis}}
|
||||||
|
require '{{importPath}}'
|
||||||
|
{{/apis}}
|
||||||
|
{{/apiInfo}}
|
||||||
|
|
||||||
|
module {{moduleName}}
|
||||||
|
# Initialize the default configuration
|
||||||
|
Swagger.configuration ||= Swagger::Configuration.new
|
||||||
|
end
|
@ -720,6 +720,18 @@
|
|||||||
"description": "successful operation",
|
"description": "successful operation",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/User"
|
"$ref": "#/definitions/User"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"application/json": {
|
||||||
|
"id": 1,
|
||||||
|
"username": "johnp",
|
||||||
|
"firstName": "John",
|
||||||
|
"lastName": "Public",
|
||||||
|
"email": "johnp@swagger.io",
|
||||||
|
"password": "-secret-",
|
||||||
|
"phone": "0123456789",
|
||||||
|
"userStatus": 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
{
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"description": "This is a sample server Petstore server. You can find out more about Swagger at <a href=\"http://swagger.io\">http://swagger.io</a> or on irc.freenode.net, #swagger. For this sample, you can use the api key \"special-key\" to test the authorization filters",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"title": "Swagger Petstore",
|
||||||
|
"termsOfService": "http://helloreverb.com/terms/",
|
||||||
|
"contact": {
|
||||||
|
"email": "apiteam@wordnik.com"
|
||||||
|
},
|
||||||
|
"license": {
|
||||||
|
"name": "Apache 2.0",
|
||||||
|
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"host": "petstore.swagger.io",
|
||||||
|
"basePath": "/v2",
|
||||||
|
"schemes": [
|
||||||
|
"http"
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/tests/requiredParams": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"summary": "Operation with required parameters",
|
||||||
|
"description": "",
|
||||||
|
"operationId": "requiredParams",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "param1",
|
||||||
|
"in": "formData",
|
||||||
|
"description": "Some required parameter",
|
||||||
|
"required": true,
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "param2",
|
||||||
|
"in": "formData",
|
||||||
|
"description": "Some optional parameter",
|
||||||
|
"required": false,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "successful operation. Retuning a simple int.",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"securityDefinitions": {
|
||||||
|
"api_key": {
|
||||||
|
"type": "apiKey",
|
||||||
|
"name": "api_key",
|
||||||
|
"in": "header"
|
||||||
|
},
|
||||||
|
"petstore_auth": {
|
||||||
|
"type": "oauth2",
|
||||||
|
"authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog",
|
||||||
|
"flow": "implicit",
|
||||||
|
"scopes": {
|
||||||
|
"write:pets": "modify pets in your account",
|
||||||
|
"read:pets": "read your pets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"CustomModel": {
|
||||||
|
"required": ["id"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "doggie"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
316
modules/swagger-codegen/src/test/resources/2_0/v1beta3.json
Normal file
316
modules/swagger-codegen/src/test/resources/2_0/v1beta3.json
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
{
|
||||||
|
"swaggerVersion": "1.2",
|
||||||
|
"apiVersion": "v1beta3",
|
||||||
|
"basePath": "https://127.0.0.1:6443",
|
||||||
|
"resourcePath": "/api/v1beta3",
|
||||||
|
"apis": [
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta3/namespaces/{namespaces}/bindings",
|
||||||
|
"description": "API at /api/v1beta3 version v1beta3",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "v1beta3.Binding",
|
||||||
|
"method": "POST",
|
||||||
|
"summary": "create a Binding",
|
||||||
|
"nickname": "createBinding",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"paramType": "path",
|
||||||
|
"name": "namespaces",
|
||||||
|
"description": "object name and auth scope, such as for teams and projects",
|
||||||
|
"required": true,
|
||||||
|
"allowMultiple": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "v1beta3.Binding",
|
||||||
|
"paramType": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "",
|
||||||
|
"required": true,
|
||||||
|
"allowMultiple": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responseMessages": [
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "OK",
|
||||||
|
"responseModel": "v1beta3.Binding"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta3/namespaces/{namespaces}/componentstatuses",
|
||||||
|
"description": "API at /api/v1beta3 version v1beta3",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "v1beta3.ComponentStatusList",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "list objects of kind ComponentStatus",
|
||||||
|
"nickname": "listComponentStatus",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"paramType": "path",
|
||||||
|
"name": "namespaces",
|
||||||
|
"description": "object name and auth scope, such as for teams and projects",
|
||||||
|
"required": true,
|
||||||
|
"allowMultiple": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"paramType": "query",
|
||||||
|
"name": "fieldSelector",
|
||||||
|
"description": "a selector to restrict the list of returned objects by their fields; defaults to everything",
|
||||||
|
"required": false,
|
||||||
|
"allowMultiple": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"paramType": "query",
|
||||||
|
"name": "labelSelector",
|
||||||
|
"description": "a selector to restrict the list of returned objects by their labels; defaults to everything",
|
||||||
|
"required": false,
|
||||||
|
"allowMultiple": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"paramType": "query",
|
||||||
|
"name": "resourceVersion",
|
||||||
|
"description": "when specified with a watch call, shows changes that occur after that particular version of a resource; defaults to changes from the beginning of history",
|
||||||
|
"required": false,
|
||||||
|
"allowMultiple": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"paramType": "query",
|
||||||
|
"name": "watch",
|
||||||
|
"description": "watch for changes to the described resources and return them as a stream of add, update, and remove notifications; specify resourceVersion",
|
||||||
|
"required": false,
|
||||||
|
"allowMultiple": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responseMessages": [
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "OK",
|
||||||
|
"responseModel": "v1beta3.ComponentStatusList"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta3/namespaces/{namespaces}/componentstatuses/{name}",
|
||||||
|
"description": "API at /api/v1beta3 version v1beta3",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "v1beta3.ComponentStatus",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "read the specified ComponentStatus",
|
||||||
|
"nickname": "readComponentStatus",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"paramType": "path",
|
||||||
|
"name": "name",
|
||||||
|
"description": "name of the ComponentStatus",
|
||||||
|
"required": true,
|
||||||
|
"allowMultiple": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"paramType": "path",
|
||||||
|
"name": "namespaces",
|
||||||
|
"description": "object name and auth scope, such as for teams and projects",
|
||||||
|
"required": true,
|
||||||
|
"allowMultiple": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responseMessages": [
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "OK",
|
||||||
|
"responseModel": "v1beta3.ComponentStatus"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"models": {
|
||||||
|
"v1beta3.ComponentStatus": {
|
||||||
|
"id": "v1beta3.ComponentStatus",
|
||||||
|
"properties": {
|
||||||
|
"apiVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "version of the schema the object should have"
|
||||||
|
},
|
||||||
|
"conditions": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "v1beta3.ObjectReference"
|
||||||
|
},
|
||||||
|
"description": "list of component conditions observed"
|
||||||
|
},
|
||||||
|
"kind": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "kind of object, in CamelCase; cannot be updated"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"$ref": "v1beta3.ObjectMeta",
|
||||||
|
"description": "standard object metadata; see http://docs.k8s.io/api-conventions.md#metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1beta3.ComponentStatusList": {
|
||||||
|
"id": "v1beta3.ComponentStatusList",
|
||||||
|
"required": [
|
||||||
|
"items"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"apiVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "version of the schema the object should have"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "v1beta3.ComponentStatus"
|
||||||
|
},
|
||||||
|
"description": "list of component status objects"
|
||||||
|
},
|
||||||
|
"kind": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "kind of object, in CamelCase; cannot be updated"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"$ref": "v1beta3.ObjectMeta",
|
||||||
|
"description": "standard list metadata; see http://docs.k8s.io/api-conventions.md#metadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1beta3.Binding": {
|
||||||
|
"id": "v1beta3.Binding",
|
||||||
|
"required": [
|
||||||
|
"target"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"apiVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "version of the schema the object should have"
|
||||||
|
},
|
||||||
|
"kind": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "kind of object, in CamelCase; cannot be updated"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"$ref": "v1beta3.ObjectMeta",
|
||||||
|
"description": "standard object metadata; see http://docs.k8s.io/api-conventions.md#metadata"
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"$ref": "v1beta3.ObjectReference",
|
||||||
|
"description": "an object to bind to"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1beta3.ObjectReference": {
|
||||||
|
"id": "v1beta3.ObjectReference",
|
||||||
|
"properties": {
|
||||||
|
"apiVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "API version of the referent"
|
||||||
|
},
|
||||||
|
"fieldPath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "if referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]"
|
||||||
|
},
|
||||||
|
"kind": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "kind of the referent"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the referent"
|
||||||
|
},
|
||||||
|
"namespace": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "namespace of the referent"
|
||||||
|
},
|
||||||
|
"resourceVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "specific resourceVersion to which this reference is made, if any: http://docs.k8s.io/api-conventions.md#concurrency-control-and-consistency"
|
||||||
|
},
|
||||||
|
"uid": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "uid of the referent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1beta3.ObjectMeta": {
|
||||||
|
"id": "v1beta3.ObjectMeta",
|
||||||
|
"properties": {
|
||||||
|
"annotations": {
|
||||||
|
"type": "any",
|
||||||
|
"description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about objects"
|
||||||
|
},
|
||||||
|
"creationTimestamp": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "RFC 3339 date and time at which the object was created; populated by the system, read-only; null for lists"
|
||||||
|
},
|
||||||
|
"deletionTimestamp": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "RFC 3339 date and time at which the object will be deleted; populated by the system when a graceful deletion is requested, read-only; if not set, graceful deletion of the object has not been requested"
|
||||||
|
},
|
||||||
|
"generateName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified"
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"type": "any",
|
||||||
|
"description": "map of string keys and values that can be used to organize and categorize objects; may match selectors of replication controllers and services"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "string that identifies an object. Must be unique within a namespace; cannot be updated"
|
||||||
|
},
|
||||||
|
"namespace": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "namespace of the object; cannot be updated"
|
||||||
|
},
|
||||||
|
"resourceVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; populated by the system, read-only; value must be treated as opaque by clients and passed unmodified back to the server: http://docs.k8s.io/api-conventions.md#concurrency-control-and-consistency"
|
||||||
|
},
|
||||||
|
"selfLink": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "URL for the object; populated by the system, read-only"
|
||||||
|
},
|
||||||
|
"uid": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "unique UUID across space and time; populated by the system; read-only"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,9 @@
|
|||||||
import com.wordnik.swagger.models._
|
|
||||||
import com.wordnik.swagger.util.Json
|
|
||||||
import io.swagger.parser._
|
|
||||||
|
|
||||||
import com.wordnik.swagger.codegen.DefaultCodegen
|
import com.wordnik.swagger.codegen.DefaultCodegen
|
||||||
|
import com.wordnik.swagger.models.properties.Property
|
||||||
|
import io.swagger.parser._
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.scalatest.junit.JUnitRunner
|
import org.scalatest.junit.JUnitRunner
|
||||||
import org.scalatest.FlatSpec
|
import org.scalatest.{FlatSpec, Matchers}
|
||||||
import org.scalatest.Matchers
|
|
||||||
|
|
||||||
import scala.collection.JavaConverters._
|
|
||||||
|
|
||||||
@RunWith(classOf[JUnitRunner])
|
@RunWith(classOf[JUnitRunner])
|
||||||
class CodegenTest extends FlatSpec with Matchers {
|
class CodegenTest extends FlatSpec with Matchers {
|
||||||
@ -95,6 +89,32 @@ class CodegenTest extends FlatSpec with Matchers {
|
|||||||
statusParam.hasMore should be (null)
|
statusParam.hasMore should be (null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it should "handle required parameters from a 2.0 spec as required when figuring out Swagger types" in {
|
||||||
|
val model = new SwaggerParser()
|
||||||
|
.read("src/test/resources/2_0/requiredTest.json")
|
||||||
|
|
||||||
|
val codegen = new DefaultCodegen() {
|
||||||
|
override def getSwaggerType(p: Property) = Option(p) match {
|
||||||
|
case Some(property) if !property.getRequired =>
|
||||||
|
"Optional<" + super.getSwaggerType(p) + ">"
|
||||||
|
case other => super.getSwaggerType(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val path = "/tests/requiredParams"
|
||||||
|
val p = model.getPaths().get(path).getGet()
|
||||||
|
val op = codegen.fromOperation(path, "get", p, model.getDefinitions)
|
||||||
|
|
||||||
|
val formParams = op.formParams
|
||||||
|
formParams.size should be(2)
|
||||||
|
val requiredParam = formParams.get(0)
|
||||||
|
requiredParam.dataType should be("Long")
|
||||||
|
|
||||||
|
val optionalParam = formParams.get(1)
|
||||||
|
optionalParam.dataType should be("Optional<string>")
|
||||||
|
|
||||||
|
op.returnType should be("Long")
|
||||||
|
}
|
||||||
|
|
||||||
it should "select main response from a 2.0 spec using the lowest 2XX code" in {
|
it should "select main response from a 2.0 spec using the lowest 2XX code" in {
|
||||||
val model = new SwaggerParser()
|
val model = new SwaggerParser()
|
||||||
.read("src/test/resources/2_0/responseSelectionTest.json")
|
.read("src/test/resources/2_0/responseSelectionTest.json")
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
import scala.collection.JavaConverters.asScalaBufferConverter
|
||||||
|
import scala.collection.JavaConverters.mapAsJavaMapConverter
|
||||||
|
import scala.collection.JavaConverters.seqAsJavaListConverter
|
||||||
|
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.scalatest.FlatSpec
|
||||||
|
import org.scalatest.Matchers
|
||||||
|
import org.scalatest.junit.JUnitRunner
|
||||||
|
|
||||||
|
import com.wordnik.swagger.codegen.examples.ExampleGenerator
|
||||||
|
import com.wordnik.swagger.models.Model
|
||||||
|
import com.wordnik.swagger.models.ModelImpl
|
||||||
|
import com.wordnik.swagger.models.Xml
|
||||||
|
import com.wordnik.swagger.models.properties.ArrayProperty
|
||||||
|
import com.wordnik.swagger.models.properties.RefProperty
|
||||||
|
import com.wordnik.swagger.models.properties.StringProperty
|
||||||
|
|
||||||
|
@RunWith(classOf[JUnitRunner])
|
||||||
|
class ExampleGeneratorTest extends FlatSpec with Matchers {
|
||||||
|
val json = "application/json"
|
||||||
|
val xml = "application/xml"
|
||||||
|
|
||||||
|
it should "check handling of recursive models" in {
|
||||||
|
val nodeType = "Node"
|
||||||
|
val ref = new RefProperty(nodeType)
|
||||||
|
val node = new ModelImpl().name(nodeType).property("name", new StringProperty())
|
||||||
|
node.property("parent", ref)
|
||||||
|
node.property("children", new ArrayProperty(ref))
|
||||||
|
node.property("wrappedChildren", new ArrayProperty(ref).xml(new Xml().wrapped(true)))
|
||||||
|
val pairType = "Pair"
|
||||||
|
val pair = new ModelImpl().name(pairType)
|
||||||
|
for (item <- Map("first" -> "First", "second" -> "Second")) {
|
||||||
|
val property = new RefProperty(nodeType)
|
||||||
|
property.setXml(new Xml().name(item._2))
|
||||||
|
pair.property(item._1, property);
|
||||||
|
}
|
||||||
|
val types = scala.collection.mutable.Buffer[String]()
|
||||||
|
val expectedTypes = List(json, xml)
|
||||||
|
val eg = new ExampleGenerator(Map[String, Model](nodeType -> node, pairType -> pair).asJava)
|
||||||
|
for (item <- eg.generate(null, expectedTypes.asJava, new RefProperty(pairType)).asScala) {
|
||||||
|
val example = item.get("example")
|
||||||
|
item.get("contentType") match {
|
||||||
|
case `xml` => {
|
||||||
|
types += xml
|
||||||
|
example should be ("<Pair>\n" +
|
||||||
|
" <Node>\n" +
|
||||||
|
" <name>string</name>\n" +
|
||||||
|
" <wrappedChildren>\n" +
|
||||||
|
" </wrappedChildren>\n" +
|
||||||
|
" </Node>\n" +
|
||||||
|
" <Node>\n" +
|
||||||
|
" <name>string</name>\n" +
|
||||||
|
" <wrappedChildren>\n" +
|
||||||
|
" </wrappedChildren>\n" +
|
||||||
|
" </Node>\n" +
|
||||||
|
"</Pair>")
|
||||||
|
}
|
||||||
|
case `json` => {
|
||||||
|
types += json
|
||||||
|
// TODO - add JSON validation
|
||||||
|
example should not be (null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
types should be (expectedTypes)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package python
|
||||||
|
|
||||||
|
import com.wordnik.swagger.codegen.languages.{PythonClientCodegen}
|
||||||
|
import io.swagger.parser.SwaggerParser
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import org.scalatest.junit.JUnitRunner
|
||||||
|
import org.scalatest.FlatSpec
|
||||||
|
import org.scalatest.Matchers
|
||||||
|
|
||||||
|
@RunWith(classOf[JUnitRunner])
|
||||||
|
class PythonTest extends FlatSpec with Matchers {
|
||||||
|
it should "convert a python model with dots" in {
|
||||||
|
val swagger = new SwaggerParser()
|
||||||
|
.read("src/test/resources/2_0/v1beta3.json")
|
||||||
|
|
||||||
|
val codegen = new PythonClientCodegen()
|
||||||
|
val simpleName = codegen.fromModel("v1beta3.Binding", swagger.getDefinitions().get("v1beta3.Binding"))
|
||||||
|
simpleName.name should be("v1beta3.Binding")
|
||||||
|
simpleName.classname should be("V1beta3Binding")
|
||||||
|
simpleName.classVarName should be("v1beta3_binding")
|
||||||
|
|
||||||
|
val compoundName = codegen.fromModel("v1beta3.ComponentStatus", swagger.getDefinitions().get("v1beta3.ComponentStatus"))
|
||||||
|
compoundName.name should be("v1beta3.ComponentStatus")
|
||||||
|
compoundName.classname should be("V1beta3ComponentStatus")
|
||||||
|
compoundName.classVarName should be("v1beta3_component_status")
|
||||||
|
|
||||||
|
val path = "/api/v1beta3/namespaces/{namespaces}/bindings"
|
||||||
|
val operation = swagger.getPaths().get(path).getPost()
|
||||||
|
val codegenOperation = codegen.fromOperation(path, "get", operation, swagger.getDefinitions())
|
||||||
|
codegenOperation.returnType should be("V1beta3Binding")
|
||||||
|
codegenOperation.returnBaseType should be("V1beta3Binding")
|
||||||
|
}
|
||||||
|
}
|
@ -6,11 +6,9 @@
|
|||||||
<version>2.1.1-M2-SNAPSHOT</version>
|
<version>2.1.1-M2-SNAPSHOT</version>
|
||||||
<relativePath>../..</relativePath>
|
<relativePath>../..</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.wordnik</groupId>
|
|
||||||
<artifactId>swagger-generator</artifactId>
|
<artifactId>swagger-generator</artifactId>
|
||||||
<packaging>war</packaging>
|
<packaging>war</packaging>
|
||||||
<name>swagger-generator</name>
|
<name>swagger-generator</name>
|
||||||
<version>2.1.1-M2-SNAPSHOT</version>
|
|
||||||
<build>
|
<build>
|
||||||
<sourceDirectory>src/main/java</sourceDirectory>
|
<sourceDirectory>src/main/java</sourceDirectory>
|
||||||
<resources>
|
<resources>
|
||||||
|
4
pom.xml
4
pom.xml
@ -450,10 +450,10 @@
|
|||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<properties>
|
<properties>
|
||||||
<swagger-parser-version>1.0.6-SNAPSHOT</swagger-parser-version>
|
<swagger-parser-version>1.0.7</swagger-parser-version>
|
||||||
<scala-version>2.10.4</scala-version>
|
<scala-version>2.10.4</scala-version>
|
||||||
<felix-version>2.3.4</felix-version>
|
<felix-version>2.3.4</felix-version>
|
||||||
<swagger-core-version>1.5.1-M2</swagger-core-version>
|
<swagger-core-version>1.5.2-M2</swagger-core-version>
|
||||||
<scala-test-version>2.1.4</scala-test-version>
|
<scala-test-version>2.1.4</scala-test-version>
|
||||||
<commons-io-version>2.3</commons-io-version>
|
<commons-io-version>2.3</commons-io-version>
|
||||||
<commons-cli-version>1.2</commons-cli-version>
|
<commons-cli-version>1.2</commons-cli-version>
|
||||||
|
227
samples/client/petstore/akka-scala/pom.xml
Normal file
227
samples/client/petstore/akka-scala/pom.xml
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.wordnik</groupId>
|
||||||
|
<artifactId>swagger-client</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>swagger-client</name>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<prerequisites>
|
||||||
|
<maven>2.2.0</maven>
|
||||||
|
</prerequisites>
|
||||||
|
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>maven-mongodb-plugin-repo</id>
|
||||||
|
<name>maven mongodb plugin repository</name>
|
||||||
|
<url>http://maven-mongodb-plugin.googlecode.com/svn/maven/repo</url>
|
||||||
|
<layout>default</layout>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.12</version>
|
||||||
|
<configuration>
|
||||||
|
<systemProperties>
|
||||||
|
<property>
|
||||||
|
<name>loggerPath</name>
|
||||||
|
<value>conf/log4j.properties</value>
|
||||||
|
</property>
|
||||||
|
</systemProperties>
|
||||||
|
<argLine>-Xms512m -Xmx1500m</argLine>
|
||||||
|
<parallel>methods</parallel>
|
||||||
|
<forkMode>pertest</forkMode>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/lib</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- attach test jar -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
<goal>test-jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>build-helper-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>add_sources</id>
|
||||||
|
<phase>generate-sources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-source</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<sources>
|
||||||
|
<source>
|
||||||
|
src/main/java</source>
|
||||||
|
</sources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>add_test_sources</id>
|
||||||
|
<phase>generate-test-sources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-test-source</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<sources>
|
||||||
|
<source>
|
||||||
|
src/test/java</source>
|
||||||
|
</sources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>2.3.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>
|
||||||
|
1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.alchim31.maven</groupId>
|
||||||
|
<artifactId>scala-maven-plugin</artifactId>
|
||||||
|
<version>${scala-maven-plugin-version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>scala-compile-first</id>
|
||||||
|
<phase>process-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-source</goal>
|
||||||
|
<goal>compile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>scala-test-compile</id>
|
||||||
|
<phase>process-test-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<args>
|
||||||
|
<arg>-feature</arg>
|
||||||
|
</args>
|
||||||
|
<jvmArgs>
|
||||||
|
<jvmArg>-Xms128m</jvmArg>
|
||||||
|
<jvmArg>-Xmx1500m</jvmArg>
|
||||||
|
</jvmArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<reporting>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.scala-tools</groupId>
|
||||||
|
<artifactId>maven-scala-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<scalaVersion>${scala-version}</scalaVersion>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</reporting>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.scala-lang</groupId>
|
||||||
|
<artifactId>scala-library</artifactId>
|
||||||
|
<version>${scala-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.wordnik</groupId>
|
||||||
|
<artifactId>swagger-core</artifactId>
|
||||||
|
<version>${swagger-core-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.scalatest</groupId>
|
||||||
|
<artifactId>scalatest_2.10</artifactId>
|
||||||
|
<version>${scala-test-version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>${junit-version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>joda-time</groupId>
|
||||||
|
<artifactId>joda-time</artifactId>
|
||||||
|
<version>${joda-time-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.joda</groupId>
|
||||||
|
<artifactId>joda-convert</artifactId>
|
||||||
|
<version>${joda-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.typesafe</groupId>
|
||||||
|
<artifactId>config</artifactId>
|
||||||
|
<version>1.2.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.typesafe.akka</groupId>
|
||||||
|
<artifactId>akka-actor_2.10</artifactId>
|
||||||
|
<version>${akka-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.spray</groupId>
|
||||||
|
<artifactId>spray-client</artifactId>
|
||||||
|
<version>${spray-version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.json4s</groupId>
|
||||||
|
<artifactId>json4s-jackson_2.10</artifactId>
|
||||||
|
<version>${json4s-jackson-version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<properties>
|
||||||
|
<scala-version>2.10.4</scala-version>
|
||||||
|
<json4s-jackson-version>3.2.11</json4s-jackson-version>
|
||||||
|
<json4s-ext-version>3.2.11</json4s-ext-version>
|
||||||
|
<spray-version>1.3.1</spray-version>
|
||||||
|
<akka-version>2.3.9</akka-version>
|
||||||
|
<joda-version>1.2</joda-version>
|
||||||
|
<joda-time-version>2.2</joda-time-version>
|
||||||
|
<swagger-core-version>1.5.0-M1</swagger-core-version>
|
||||||
|
<maven-plugin.version>1.0.0</maven-plugin.version>
|
||||||
|
|
||||||
|
<junit-version>4.8.1</junit-version>
|
||||||
|
<scala-maven-plugin-version>3.1.5</scala-maven-plugin-version>
|
||||||
|
<scala-test-version>2.1.3</scala-test-version>
|
||||||
|
</properties>
|
||||||
|
</project>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user