diff --git a/bin/generate-scala-lib.sh b/bin/generate-scala-lib.sh
new file mode 100755
index 00000000000..a544785afe7
--- /dev/null
+++ b/bin/generate-scala-lib.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+if [ $# -ne 4 ]
+then
+ echo "Error in $0 - Invalid Argument Count"
+ echo "Syntax: $0 location_of_service api_key package_name library_root"
+ exit
+fi
+
+echo "" > classpath.txt
+for file in `ls lib`;
+ do echo -n 'lib/' >> classpath.txt;
+ echo -n $file >> classpath.txt;
+ echo -n ':' >> classpath.txt;
+done
+for file in `ls build`;
+ do echo -n 'build/' >> classpath.txt;
+ echo -n $file >> classpath.txt;
+ echo -n ':' >> classpath.txt;
+done
+
+export CLASSPATH=$(cat classpath.txt):conf/scala/templates
+export JAVA_OPTS="${JAVA_OPTS} -Dproperty=Xmx2g"
+scala $WORDNIK_OPTS $JAVA_CONFIG_OPTIONS $JAVA_OPTS -cp $CLASSPATH com.wordnik.swagger.codegen.config.scala.ScalaLibCodeGen "$@"
diff --git a/conf/scala/sample/build.xml b/conf/scala/sample/build.xml
new file mode 100644
index 00000000000..b482a4eddb7
--- /dev/null
+++ b/conf/scala/sample/build.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/scala/sample/ivy.xml b/conf/scala/sample/ivy.xml
new file mode 100644
index 00000000000..b2573f73d69
--- /dev/null
+++ b/conf/scala/sample/ivy.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/scala/sample/ivysettings.xml b/conf/scala/sample/ivysettings.xml
new file mode 100644
index 00000000000..ea8e09b9f5b
--- /dev/null
+++ b/conf/scala/sample/ivysettings.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/scala/sample/java_code_gen_conf.json b/conf/scala/sample/java_code_gen_conf.json
new file mode 100644
index 00000000000..74db34b345c
--- /dev/null
+++ b/conf/scala/sample/java_code_gen_conf.json
@@ -0,0 +1,27 @@
+{
+ "apiUrl":"http://localhost:8002/api/",
+
+ "apiKey":"special-key",
+
+ "defaultServiceBaseClass":"Object",
+
+ "defaultModelBaseClass":"Object",
+
+ "serviceBaseClasses":{},
+
+ "defaultModelImports":[],
+
+ "defaultServiceImports":[],
+
+ "modelPackageName":"com.wordnik.swagger.sample.sdk.java.model",
+
+ "apiPackageName":"com.wordnik.swagger.sample.sdk.java.api",
+
+ "ignoreMethods":[],
+
+ "ignoreModels":[],
+
+ "outputDirectory":"../swagger-sample-app/sdk-libs/src/main/java/com/wordnik/swagger/sample/sdk/java",
+
+ "libraryHome":"../swagger-sample-app/sdk-libs"
+}
diff --git a/conf/scala/sample/lib-test-data.json b/conf/scala/sample/lib-test-data.json
new file mode 100644
index 00000000000..24d529e981d
--- /dev/null
+++ b/conf/scala/sample/lib-test-data.json
@@ -0,0 +1,42 @@
+{
+ "userList":[
+ {
+ "username":"testuser1",
+ "password":"password1",
+ "email":"test1@dummy.com"
+ },
+ {
+ "username":"testuser2",
+ "password":"password2",
+ "email":"test2@dummy.com"
+ }
+ ],
+ "petList":[
+ {
+ "id":101,
+ "name":"pet1",
+ "photoUrls":["url1","url2"],
+ "tags":[
+ {
+ "id":1,
+ "name":"tag1"
+ },
+ {
+ "id":2,
+ "name":"tag2"
+ }
+ ],
+ "status":"available",
+ "category":{"id":1,"name":"cat1"}
+ }
+ ],
+ "orderList":[
+ {
+ "id":101,
+ "petId":1,
+ "quantity":1,
+ "status":"placed",
+ "shipDate":13456789
+ }
+ ]
+}
diff --git a/conf/scala/sample/lib-test-script.json b/conf/scala/sample/lib-test-script.json
new file mode 100644
index 00000000000..7953c939cfb
--- /dev/null
+++ b/conf/scala/sample/lib-test-script.json
@@ -0,0 +1,265 @@
+{
+ "resources" : [
+ {
+ "id" : 1,
+ "name" : "Find Per by Id",
+ "httpMethod" : "GET",
+ "path" : "/pet.{format}/{petId}",
+ "suggestedMethodName" : "getPetById"
+ },
+ {
+ "id" : 2,
+ "name" : "Find pets by status",
+ "httpMethod" : "GET",
+ "path" : "/pet.{format}/findByStatus",
+ "suggestedMethodName" : "findPetsByStatus"
+ },
+ {
+ "id" : 3,
+ "name" : "Find pets by tags",
+ "httpMethod" : "GET",
+ "path" : "/pet.{format}/findByTags",
+ "suggestedMethodName" : "findPetsByTags"
+ },
+ {
+ "id" : 4,
+ "name" : "Add a pet",
+ "httpMethod" : "POST",
+ "path" : "/pet.{format}",
+ "suggestedMethodName" : "addPet"
+ },
+ {
+ "id" : 5,
+ "name" : "Update a pet",
+ "httpMethod" : "PUT",
+ "path" : "/pet.{format}",
+ "suggestedMethodName" : "updatePet"
+ },
+ {
+ "id" : 6,
+ "name" : "Create user",
+ "httpMethod" : "POST",
+ "path" : "/user.{format}",
+ "suggestedMethodName" : "createUser"
+ },
+ {
+ "id" : 7,
+ "name" : "Update user",
+ "httpMethod" : "PUT",
+ "path" : "/user.{format}/{username}",
+ "suggestedMethodName" : "updateUser"
+ },
+ {
+ "id" : 8,
+ "name" : "Delete user",
+ "httpMethod" : "DELETE",
+ "path" : "/user.{format}/{username}",
+ "suggestedMethodName" : "deleteUser"
+ },
+ {
+ "id" : 9,
+ "name" : "Get user by user name",
+ "httpMethod" : "GET",
+ "path" : "/user.{format}/{username}",
+ "suggestedMethodName" : "getUserByName"
+ },
+ {
+ "id" : 10,
+ "name" : "Login",
+ "httpMethod" : "GET",
+ "path" : "/user.{format}/login",
+ "suggestedMethodName" : "loginUser"
+ },
+ {
+ "id" : 11,
+ "name" : "Logout",
+ "httpMethod" : "GET",
+ "path" : "/user.{format}/logout",
+ "suggestedMethodName" : "logoutUser"
+ },
+ {
+ "id" : 12,
+ "name" : "Find order by id",
+ "httpMethod" : "GET",
+ "path" : "/store.{format}/order/{orderId}",
+ "suggestedMethodName" : "getOrderById"
+ },
+ {
+ "id" : 13,
+ "name" : "Delete order by id",
+ "httpMethod" : "DELETE",
+ "path" : "/store.{format}/order/{orderId}",
+ "suggestedMethodName" : "deleteOrder"
+ },
+ {
+ "id" : 14,
+ "name" : "Create order",
+ "httpMethod" : "POST",
+ "path" : "/store.{format}/order",
+ "suggestedMethodName" : "placeOrder"
+ }
+ ],
+ "testSuites" : [
+ {
+ "id" : 1,
+ "name" : "Test User service related APIs",
+ "testCases" : [
+ {
+ "name" : "Create User",
+ "id" : 1,
+ "resourceId" : 6,
+ "input" : {
+ "postData":"${input.userList[0]}"
+ },
+ "assertions" : [
+ {
+ "actualOutput" : "${output(1.1)}",
+ "condition" : "!=",
+ "expectedOutput" : "EXCEPTION"
+ }
+ ]
+ },
+ {
+ "name" : "Login User",
+ "id" : 2,
+ "resourceId" : 10,
+ "input" : {
+ "username":"${input.userList[0].username}",
+ "password":"${input.userList[0].password}"
+ },
+ "assertions" : [
+ {
+ "actualOutput" : "${output(1.2)}",
+ "condition" : "!=",
+ "expectedOutput" : "EXCEPTION"
+ }
+ ]
+ },
+ {
+ "name" : "Find user by name",
+ "id" : 3,
+ "resourceId" : 9,
+ "input" : {
+ "username":"${input.userList[0].username}"
+ },
+ "assertions" : [
+ {
+ "actualOutput" : "${output(1.3).username}",
+ "condition" : "==",
+ "expectedOutput" : "${input.userList[0].username}"
+ }
+ ]
+ },
+ {
+ "name" : "Delete user by name",
+ "id" : 4,
+ "resourceId" : 9,
+ "input" : {
+ "username":"${input.userList[0].username}"
+ },
+ "assertions" : [
+ {
+ "actualOutput" : "${output(1.4)}",
+ "condition" : "!=",
+ "expectedOutput" : "EXCEPTION"
+ }
+ ]
+ }
+
+
+ ]
+ },
+ {
+ "id" : 2,
+ "name" : "Test Pet service related APIs",
+ "testCases" : [
+ {
+ "name" : "Add pet",
+ "id" : 1,
+ "resourceId" : 4,
+ "input" : {
+ "postData":"${input.petList[0]}"
+ },
+ "assertions" : [
+ {
+ "actualOutput" : "${output(2.1)}",
+ "condition" : "!=",
+ "expectedOutput" : "EXCEPTION"
+ }
+ ]
+ },
+ {
+ "name" : "Find pet by id",
+ "id" : 2,
+ "resourceId" : 1,
+ "input" : {
+ "petId":"1"
+ },
+ "assertions" : [
+ {
+ "actualOutput" : "${output(2.2)}",
+ "condition" : "!=",
+ "expectedOutput" : "NULL"
+ }
+ ]
+ },
+ {
+ "name" : "Find pet by status",
+ "id" : 3,
+ "resourceId" : 2,
+ "input" : {
+ "status":"available,sold,pending"
+ },
+ "assertions" : [
+ {
+ "actualOutput" : "${output(2.3).size}",
+ "condition" : ">",
+ "expectedOutput" : "0"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id" : 3,
+ "name" : "Test Store service related APIs",
+ "testCases" : [
+ {
+ "name" : "Find order by id",
+ "id" : 1,
+ "resourceId" : 12,
+ "input" : {
+ "orderId":"1"
+ },
+ "assertions" : [
+ {
+ "actualOutput" : "${output(3.1)}",
+ "condition" : "!=",
+ "expectedOutput" : "NULL"
+ }
+ ]
+ },
+ {
+ "name" : "Place order",
+ "id" : 2,
+ "resourceId" : 14,
+ "input" : {
+ "postData":"${input.orderList[0]}"
+ },
+ "assertions" : [
+ {
+ "actualOutput" : "${output(1.2)}",
+ "condition" : "!=",
+ "expectedOutput" : "EXCEPTION"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+
+
+
+
+
\ No newline at end of file
diff --git a/conf/scala/structure/src/main/java/com/wordnik/swagger/annotations/AllowableValues.java b/conf/scala/structure/src/main/java/com/wordnik/swagger/annotations/AllowableValues.java
new file mode 100644
index 00000000000..7d81cce8f52
--- /dev/null
+++ b/conf/scala/structure/src/main/java/com/wordnik/swagger/annotations/AllowableValues.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * Annotation used to provide list of possible values
+ * @author ramesh
+ *
+ */
+@Target({ElementType.FIELD,ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AllowableValues {
+
+ String value() default "";
+}
diff --git a/conf/scala/structure/src/main/java/com/wordnik/swagger/annotations/MethodArgumentNames.java b/conf/scala/structure/src/main/java/com/wordnik/swagger/annotations/MethodArgumentNames.java
new file mode 100644
index 00000000000..a178848f74d
--- /dev/null
+++ b/conf/scala/structure/src/main/java/com/wordnik/swagger/annotations/MethodArgumentNames.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Target({ElementType.FIELD,ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MethodArgumentNames {
+ String value() default "";
+}
diff --git a/conf/scala/structure/src/main/java/com/wordnik/swagger/annotations/Required.java b/conf/scala/structure/src/main/java/com/wordnik/swagger/annotations/Required.java
new file mode 100644
index 00000000000..3eda04d2f7d
--- /dev/null
+++ b/conf/scala/structure/src/main/java/com/wordnik/swagger/annotations/Required.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used to indicate given property or field is required or not
+ * @author ramesh
+ *
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Required {
+
+}
diff --git a/conf/scala/structure/src/main/java/com/wordnik/swagger/common/APIInvoker.java b/conf/scala/structure/src/main/java/com/wordnik/swagger/common/APIInvoker.java
new file mode 100644
index 00000000000..6f2d5c4b2db
--- /dev/null
+++ b/conf/scala/structure/src/main/java/com/wordnik/swagger/common/APIInvoker.java
@@ -0,0 +1,268 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.common;
+
+import java.io.IOException;
+import java.lang.String;
+import java.util.Map;
+import java.util.List;
+import java.util.HashMap;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import com.wordnik.swagger.exception.APIException;
+import com.wordnik.swagger.exception.APIExceptionCodes;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.DeserializationConfig.Feature;
+import org.codehaus.jackson.map.SerializationConfig;
+import org.codehaus.jackson.type.TypeReference;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.WebResource.Builder;
+import com.sun.jersey.api.client.filter.LoggingFilter;
+
+
+/**
+ * Provides method to initialize the api server settings and also handles the logic related to invoking the API server
+ * along with serealizing and deserializing input and output responses.
+ *
+ * This is also a Base class for all API classes
+ *
+ * @author ramesh
+ *
+ */
+public class APIInvoker {
+
+ private static String apiServer = "http://api.wordnik.com/v4";
+ private static SecurityHandler securityHandler = null;
+ private static boolean loggingEnabled;
+ private static Logger logger = null;
+
+ protected static String POST = "POST";
+ protected static String GET = "GET";
+ protected static String PUT = "PUT";
+ protected static String DELETE = "DELETE";
+ public static ObjectMapper mapper = new ObjectMapper();
+ static{
+ mapper.getDeserializationConfig().set(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ mapper.getSerializationConfig().set(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
+ mapper.configure(SerializationConfig.Feature.WRITE_NULL_PROPERTIES, false);
+ mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
+ }
+
+ /**
+ * Initializes the API communication with required inputs.
+ * @param securityHandler security handler responsible for populating necessary security invocation while making API server calls
+ * @param apiServer Sets the URL for the API server. It is defaulted to the server
+ * used while building the driver. This value should be provided while testing the APIs against
+ * test servers or if there is any changes in production server URLs.
+ * @param enableLogging This will enable the logging using Jersey logging filter. Refer the following documentation
+ * for more details. {@link com.sun.jersey.api.client.filter.LoggingFilter}. Default output is sent to system.out.
+ * Create a logger ({@link java.util.logging.Logger} class and set using setLogger method.
+ */
+ public static void initialize(SecurityHandler securityHandler, String apiServer, boolean enableLogging) {
+ setSecurityHandler(securityHandler);
+ if(apiServer != null && apiServer.length() > 0) {
+ if(apiServer.substring(apiServer.length()-1).equals("/")){
+ apiServer = apiServer.substring(0, apiServer.length()-1);
+ }
+ setApiServer(apiServer);
+ }
+ loggingEnabled = enableLogging;
+ }
+
+ /**
+ * Set the logger instance used for Jersey logging.
+ * @param aLogger
+ */
+ public static void setLogger(Logger aLogger) {
+ logger = aLogger;
+ }
+
+ /**
+ * Gets the API key used for server communication.
+ * This value is set using initialize method.
+ * @return
+ */
+ public static SecurityHandler setSecurityHandler() {
+ return securityHandler;
+ }
+
+ private static void setSecurityHandler(SecurityHandler aSecurityHandler) {
+ securityHandler = aSecurityHandler;
+ }
+
+ /**
+ * Sets the URL for the API server. It is defaulted to the server used while building the driver.
+ * @return
+ */
+ private static String getApiServer() {
+ return apiServer;
+ }
+
+ public static void setApiServer(String server) {
+ apiServer = server;
+ }
+
+
+
+ /**
+ * Invokes the API and returns the response as json string.
+ *
+ * This is an internal method called by individual APIs for communication. It sets the required security information
+ * based ons ecuroty handler
+ *
+ * @param resourceURL - URL for the rest resource
+ * @param method - Method we should use for communicating to the back end.
+ * @param postObject - if the method is POST, provide the object that should be sent as part of post request.
+ * @return JSON response of the API call.
+ * @throws com.wordnik.swagger.exception.APIException if the call to API server fails.
+ */
+ public static String invokeAPI(String resourceURL, String method, Map queryParams, Object postData) throws APIException {
+
+
+ Client apiClient = Client.create();
+
+ //check for app server values
+ if(getApiServer() == null || getApiServer().length() == 0) {
+ String[] args = {getApiServer()};
+ throw new APIException(APIExceptionCodes.API_SERVER_NOT_VALID, args);
+ }
+
+ //initialize the logger if needed
+ if(loggingEnabled) {
+ if(logger == null) {
+ apiClient.addFilter(new LoggingFilter());
+ }else{
+ apiClient.addFilter(new LoggingFilter(logger));
+ }
+ }
+
+ //make the communication
+ resourceURL = getApiServer() + resourceURL;
+ if(queryParams.keySet().size() > 0){
+ int i=0;
+ for(String paramName : queryParams.keySet()){
+ String symbol = "&";
+ if(i==0){
+ symbol = "?";
+ }
+ resourceURL = resourceURL + symbol + paramName + "=" + queryParams.get(paramName);
+ i++;
+ }
+ }
+ Map headerMap = new HashMap();
+ if(securityHandler != null){
+ securityHandler.populateSecurityInfo(resourceURL, headerMap);
+ }
+ WebResource aResource = apiClient.resource(resourceURL);
+
+
+ //set the required HTTP headers
+ Builder builder = aResource.type("application/json");
+ for(String key : headerMap.keySet()){
+ builder.header(key, headerMap.get(key));
+ }
+
+ ClientResponse clientResponse = null;
+ if(method.equals(GET)) {
+ clientResponse = builder.get(ClientResponse.class);
+ }else if (method.equals(POST)) {
+ clientResponse = builder.post(ClientResponse.class, serialize(postData));
+ }else if (method.equals(PUT)) {
+ clientResponse = builder.put(ClientResponse.class, serialize(postData));
+ }else if (method.equals(DELETE)) {
+ clientResponse = builder.delete(ClientResponse.class);
+ }
+
+ //process the response
+ if(clientResponse.getClientResponseStatus() == ClientResponse.Status.OK) {
+ String response = clientResponse.getEntity(String.class);
+ return response;
+ }else{
+ int responseCode = clientResponse.getClientResponseStatus().getStatusCode() ;
+ throw new APIException(responseCode, clientResponse.getEntity(String.class));
+ }
+ }
+
+ /**
+ * De-serialize the object from String to object of type input class name.
+ * @param response
+ * @param inputClassName
+ * @return
+ */
+ public static Object deserialize(String response, Class inputClassName) throws APIException {
+ try {
+ Object responseObject = mapper.readValue(response, inputClassName);
+ return responseObject;
+ } catch (IOException ioe) {
+ String[] args = new String[]{response, inputClassName.toString()};
+ throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, args, "Error in coversting response json value to java object : " + ioe.getMessage(), ioe);
+ }
+ }
+
+
+ /**
+ * serialize the object from String to input object.
+ * @param input
+ * @return
+ */
+ public static String serialize(Object input) throws APIException {
+ try {
+ if(input != null) {
+ return mapper.writeValueAsString(input);
+ }else{
+ return "";
+ }
+ } catch (IOException ioe) {
+ throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JAVA_TO_JSON, "Error in coverting input java to json : " + ioe.getMessage(), ioe);
+ }
+ }
+
+
+ /**
+ * Overloaded method for returning the path value
+ * For a string value an empty value is returned if the value is null
+ * @param value
+ * @return
+ */
+ public static String toPathValue(String value) {
+ return value == null ? "" : value;
+ }
+
+ /**
+ * Overloaded method for returning a path value
+ * For a list of objects a comma separated string is returned
+ * @param objects
+ * @return
+ */
+ public static String toPathValue(List objects) {
+ StringBuilder out = new StringBuilder();
+ for(Object o: objects){
+ out.append(o.toString());
+ out.append(",");
+ }
+ if(out.indexOf(",") != -1) {
+ return out.substring(0, out.lastIndexOf(",") );
+ }
+ return out.toString();
+ }
+}
diff --git a/conf/scala/structure/src/main/java/com/wordnik/swagger/common/SecurityHandler.java b/conf/scala/structure/src/main/java/com/wordnik/swagger/common/SecurityHandler.java
new file mode 100644
index 00000000000..a2224f85825
--- /dev/null
+++ b/conf/scala/structure/src/main/java/com/wordnik/swagger/common/SecurityHandler.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.common;
+
+import java.util.Map;
+
+/**
+ * Provide methods that are responsible for handling security aspect while communicating with the backend server.
+ *
+ * Example: For some cases API key may need to be passed in the headers for all server communication and some times
+ * user authentication token may need to be passed along with api key.
+ *
+ * Implementers of this class are responsible for handling storing information related to secutiry and sending it
+ * along with all API calls
+ *
+ * User: ramesh
+ * Date: 4/12/11
+ * Time: 5:46 PM
+ */
+public interface SecurityHandler {
+
+ /**
+ * Populate the security infomration in http headers map and/or reqsource URL.
+ *
+ * Value spopulated in the http headers map will be set as http headers while making the server communication.
+ *
+ * Depending on the usecase requried information can be added to either of them or both.
+ *
+ * @param resourceURL
+ * @param headers
+ */
+ public void populateSecurityInfo(String resourceURL, Map httpHeaders);
+}
\ No newline at end of file
diff --git a/conf/scala/structure/src/main/java/com/wordnik/swagger/common/StringValue.java b/conf/scala/structure/src/main/java/com/wordnik/swagger/common/StringValue.java
new file mode 100644
index 00000000000..6fcbdfcd52d
--- /dev/null
+++ b/conf/scala/structure/src/main/java/com/wordnik/swagger/common/StringValue.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.common;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: ramesh
+ * Date: 4/12/11
+ * Time: 5:46 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class StringValue {
+
+ String word;
+
+
+ public String getWord() {
+ return word;
+ }
+
+ public void setWord(String value) {
+ this.word = value;
+ }
+}
diff --git a/conf/scala/structure/src/main/java/com/wordnik/swagger/exception/APIException.java b/conf/scala/structure/src/main/java/com/wordnik/swagger/exception/APIException.java
new file mode 100644
index 00000000000..1511175a97c
--- /dev/null
+++ b/conf/scala/structure/src/main/java/com/wordnik/swagger/exception/APIException.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.exception;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonMethod;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Exception that is thrown if there are any issues in invoking Wordnik API.
+ *
+ * Each exception carries a code and message. Code can be either HTTP error response code {@link com.sun.jersey.api.client.ClientResponse.Status}
+ * or The list of possible Wordnik exception code that are listed in the interface {@link APIExceptionCodes}.
+ * User: ramesh
+ * Date: 3/31/11
+ * Time: 9:27 AM
+ */
+public class APIException extends Exception {
+
+ private String message;
+
+ private int code;
+
+ private String[] args;
+
+ @JsonCreator
+ public APIException() {
+ }
+
+ public APIException(String message) {
+ super(message);
+ }
+
+ public APIException(int code) {
+ this.code = code;
+ }
+
+ public APIException(int code, String message, Throwable t) {
+ super(message, t);
+ this.message = message;
+ this.code = code;
+ }
+
+ public APIException(int code, String[] args, String message, Throwable t) {
+ super(message, t);
+ this.message = message;
+ this.code = code;
+ this.args = args;
+ }
+
+ public APIException(int code, String message) {
+ super(message);
+ this.message = message;
+ this.code = code;
+ }
+
+ public APIException(int code, String[] args, String message) {
+ super(message);
+ this.message = message;
+ this.code = code;
+ this.args = args;
+ }
+
+ public APIException(int code, String[] args) {
+ this.code = code;
+ this.args = args;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+}
diff --git a/conf/scala/structure/src/main/java/com/wordnik/swagger/exception/APIExceptionCodes.java b/conf/scala/structure/src/main/java/com/wordnik/swagger/exception/APIExceptionCodes.java
new file mode 100644
index 00000000000..56ec3c65837
--- /dev/null
+++ b/conf/scala/structure/src/main/java/com/wordnik/swagger/exception/APIExceptionCodes.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.exception;
+
+/**
+ * Lists all the possible exception codes
+ * @author ramesh
+ *
+ */
+public interface APIExceptionCodes {
+
+ /**
+ * System exception.
+ */
+ public static final int SYSTEM_EXCEPTION = 0;
+
+ /**
+ * With Arguments as current key.
+ */
+ public static final int API_KEY_NOT_VALID = 1000;
+ /**
+ * With arguments as current token value
+ */
+ public static final int AUTH_TOKEN_NOT_VALID = 1001;
+ /**
+ * With arguments as input JSON and output class anme
+ */
+ public static final int ERROR_CONVERTING_JSON_TO_JAVA = 1002;
+ /**
+ * With arguments as JAVA class name
+ */
+ public static final int ERROR_CONVERTING_JAVA_TO_JSON = 1003;
+
+ public static final int ERROR_FROM_WEBSERVICE_CALL = 1004;
+ /**
+ * With arguments as current API server name
+ */
+ public static final int API_SERVER_NOT_VALID = 1005;
+
+}
diff --git a/conf/scala/templates/EnumObject.st b/conf/scala/templates/EnumObject.st
new file mode 100644
index 00000000000..545ba15eae0
--- /dev/null
+++ b/conf/scala/templates/EnumObject.st
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package $packageName$
+
+$imports:{ import |
+import $import$;
+}$
+
+/**
+ * $enum.description$
+ * NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
+ * @author tony
+ *
+ */
+object $className$ {
+ $values: { value | var $value.name$ = $value.value$};separator="\n"$
+}
diff --git a/conf/scala/templates/ModelObject.st b/conf/scala/templates/ModelObject.st
new file mode 100644
index 00000000000..c895a194eb6
--- /dev/null
+++ b/conf/scala/templates/ModelObject.st
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package $packageName$
+
+import com.wordnik.swagger.runtime.annotations._
+
+import scala.reflect.BeanProperty
+
+import scala.collection.JavaConversions._
+
+$imports:{ import |
+import $import$
+}$
+
+/**
+ * $model.description$
+ *
+ * NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
+ *
+ * @author tony
+ *
+ */
+class $className$ extends $extends$ {
+
+$fields:{ field |
+ /**
+ * $field.description$
+ * $if(field.required)$@Required$endif$
+ * $if(field.allowableValues)$@AllowableValues(value="$field.allowedValuesString$")$endif$
+ */
+$if(field.fieldDefinition.hasListResponse)$
+ var $field.fieldDefinition.name$ $field.fieldDefinition.initialization$
+ def get$field.fieldDefinition.NameForMethod$:java.util.List[$field.fieldDefinition.collectionItemType$] = {
+ $field.fieldDefinition.name$.toList
+ }
+ def set$field.fieldDefinition.NameForMethod$(args:java.util.List[$field.fieldDefinition.collectionItemType$]) = {
+ $field.fieldDefinition.name$.clear
+ args.foreach(arg=>$field.fieldDefinition.name$ += arg)
+ }
+ $\r$
+$else$
+ @BeanProperty
+ var $field.fieldDefinition.name$:$field.fieldDefinition.returnType$ $field.fieldDefinition.initialization$$\r\r$
+$endif$
+}$ override def toString:String = {
+ "[" +
+ $fields:{ field | "$field.fieldDefinition.name$:" + $field.fieldDefinition.name$};separator=" + \r "$ + "]"
+ }
+}
diff --git a/conf/scala/templates/ResourceObject.st b/conf/scala/templates/ResourceObject.st
new file mode 100644
index 00000000000..b1846fce76b
--- /dev/null
+++ b/conf/scala/templates/ResourceObject.st
@@ -0,0 +1,137 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+package $packageName$
+
+import $modelPackageName$._
+
+import org.codehaus.jackson.map.DeserializationConfig.Feature
+import org.codehaus.jackson.map.ObjectMapper
+import org.codehaus.jackson.`type`.TypeReference
+import com.wordnik.swagger.runtime.annotations._
+import com.wordnik.swagger.runtime.common._
+import com.wordnik.swagger.runtime.exception._
+
+import java.io.IOException
+
+import scala.collection.mutable._
+import scala.collection.JavaConversions._
+
+$imports:{ import |
+import $import$
+}$
+
+/**
+ *
+ * NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
+ * @author tony
+ *
+ */
+object $resource$ {
+
+$methods:{ method |
+ /**
+ * $method.title$
+ *
+$if(method.description)$
+ * $method.description$
+ * $endif$
+ * $method.arguments:{ argument |@param $argument.name$ $argument.description$
+$if(argument.allowedValues)$
+ * Allowed values are - $argument.allowedValues$ $endif$ }$
+$if(!method.responseVoid)$
+ * @return $method.returnValue$ {@link $method.returnClassName$} $endif$
+ * @throws APIException $method.exceptionDescription$
+ */
+$if(method.hasArguments)$
+ @MethodArgumentNames(value="$method.argumentNames; separator=", "$")
+$endif$
+
+ @throws(classOf[APIException])
+ def $method.name$($method.argumentDefinitions; separator=", "$) $if(method.hasResponseValue)$:$method.returnValue$$endif$ = {
+
+ //parse inputs
+ var resourcePath = "$method.resourcePath$".replace("{format}","json")
+ val method = "$method.methodType$";
+ var queryParams = new HashMap[String, String]
+$if(!method.inputModel)$
+$method.queryParameters:{ argument |
+ if(null != $argument.name$) {
+ queryParams += "$argument.name$" -> APIInvoker.toPathValue($argument.name$)
+ }
+}$
+$method.pathParameters:{ argument |
+ if(null != $argument.name$) {
+ resourcePath = resourcePath.replace("{$argument.name$}", $argument.name$)
+ }
+}$
+$endif$
+$if(method.inputModel)$
+$method.queryParameters:{ argument |
+ if(null != $argument.inputModelClassArgument$ && null != $argument.methodNameFromModelClass$ ) {
+ queryParams += "$argument.name$" -> $argument.methodNameFromModelClass$)
+ }
+}$
+$method.pathParameters:{ argument |
+ if(null != $argument.inputModelClassArgument$ && null != $argument.methodNameFromModelClass$ ) {
+ resourcePath = resourcePath.replace("{$argument.name$}", $argument.methodNameFromModelClass$)
+ }
+}$
+$endif$
+ //make the API Call
+$if(method.hasResponseValue)$
+ $if(method.postObject)$
+ val response = APIInvoker.invokeAPI(resourcePath, method, queryParams, postData)
+ $else$
+ val response = APIInvoker.invokeAPI(resourcePath, method, queryParams, null)
+ $endif$
+$else$
+ $if(method.postObject)$
+ APIInvoker.invokeAPI(resourcePath, method, queryParams, postData)
+ $else$
+ APIInvoker.invokeAPI(resourcePath, method, queryParams, null)
+ $endif$
+$endif$
+$if(!method.responseVoid)$
+
+$if(method.hasResponseValue)$
+ if(null == response || response.length() == 0){
+ null
+ }
+$endif$
+$if(!method.returnValueList)$
+$if(method.hasResponseValue)$
+ //create output objects if the response has more than one object
+ val responseObject = APIInvoker.deserialize(response, classOf[$method.returnClassName$]).asInstanceOf[$method.returnValue$]
+ responseObject
+$endif$
+$endif$
+$if(method.returnValueList)$
+ val typeRef = new TypeReference[Array[$method.returnClassName$]] {}
+ try {
+ val responseObject = APIInvoker.mapper.readValue(response, typeRef).asInstanceOf[Array[$method.returnClassName$]]
+ responseObject.toList
+ } catch {
+ case ioe:IOException => {
+ val args = Array(response, typeRef.toString())
+ throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, args, "Error in converting response json value to java object : " + ioe.getMessage(), ioe)
+ }
+ case _ => throw new APIException(APIExceptionCodes.ERROR_CONVERTING_JSON_TO_JAVA, "Error in converting response json value to java object")
+ }
+$endif$
+$endif$
+ }
+}$
+}
diff --git a/conf/scala/templates/VersionChecker.st b/conf/scala/templates/VersionChecker.st
new file mode 100644
index 00000000000..0f62b107508
--- /dev/null
+++ b/conf/scala/templates/VersionChecker.st
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package $packageName$
+
+/**
+ *
+ * Maintains the compatible server version against which the drive is written
+ * NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually.
+ * @author tony
+ *
+ */
+class VersionChecker {
+ var compatibleVersion = "$apiVersion$"
+
+ /**
+ * Gets the version against which the library code was written
+ */
+ def getCompatibleVersion():String = compatibleVersion
+}
\ No newline at end of file
diff --git a/src/main/java/com/wordnik/swagger/codegen/FieldDefinition.java b/src/main/java/com/wordnik/swagger/codegen/FieldDefinition.java
index ce49c3ea171..7a4fb6afeb1 100644
--- a/src/main/java/com/wordnik/swagger/codegen/FieldDefinition.java
+++ b/src/main/java/com/wordnik/swagger/codegen/FieldDefinition.java
@@ -33,11 +33,47 @@ public class FieldDefinition {
private String collectionItemName;
+ private boolean hasListResponse;
+ private boolean hasMapResponse;
+ private boolean hasSetResponse;
+
+
+ public boolean isHasListResponse() {
+ return hasListResponse;
+ }
+
+ public void setHasListResponse(boolean hasListResponse) {
+ this.hasListResponse = hasListResponse;
+ }
+
+ public boolean isHasMapResponse() {
+ return hasMapResponse;
+ }
+
+ public void setHasMapResponse(boolean hasMapResponse) {
+ this.hasMapResponse = hasMapResponse;
+ }
+
+ public boolean isHasSetResponse() {
+ return hasSetResponse;
+ }
+
+ public void setHasSetResponse(boolean hasSetResponse) {
+ this.hasSetResponse = hasSetResponse;
+ }
+
public String getReturnType() {
return returnType;
}
public void setReturnType(String returnType) {
+ if(returnType.startsWith("List")){
+ hasListResponse = true;
+ }else if(returnType.startsWith("Set")){
+ hasSetResponse = true;
+ }else if(returnType.startsWith("Map")){
+ hasMapResponse = true;
+ }
this.returnType = returnType;
}
diff --git a/src/main/java/com/wordnik/swagger/codegen/LibraryCodeGenerator.java b/src/main/java/com/wordnik/swagger/codegen/LibraryCodeGenerator.java
index ea9750c7c05..1f2cbb2a826 100644
--- a/src/main/java/com/wordnik/swagger/codegen/LibraryCodeGenerator.java
+++ b/src/main/java/com/wordnik/swagger/codegen/LibraryCodeGenerator.java
@@ -19,7 +19,6 @@ import com.wordnik.swagger.codegen.api.SwaggerResourceDocReader;
import com.wordnik.swagger.codegen.config.*;
import com.wordnik.swagger.codegen.config.ApiConfiguration;
import com.wordnik.swagger.codegen.config.common.CamelCaseNamingPolicyProvider;
-import com.wordnik.swagger.codegen.config.java.JavaDataTypeMappingProvider;
import com.wordnik.swagger.codegen.exception.CodeGenerationException;
import com.wordnik.swagger.codegen.resource.*;
import org.antlr.stringtemplate.StringTemplate;
@@ -55,9 +54,14 @@ public class LibraryCodeGenerator {
protected DataTypeMappingProvider dataTypeMappingProvider;
protected RulesProvider codeGenRulesProvider;
protected NamingPolicyProvider nameGenerator;
+
+ public LibraryCodeGenerator(){}
public LibraryCodeGenerator(String configPath){
-
+ initializeWithConfigPath(configPath);
+ }
+
+ protected void initializeWithConfigPath(String configPath){
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@@ -65,14 +69,15 @@ public class LibraryCodeGenerator {
this.setApiConfig(readApiConfiguration(configPath, mapper, configFile));
this.setCodeGenRulesProvider(readRulesProviderConfig(configPath, mapper, configFile));
this.setLanguageConfig( initializeLangConfig(readLanguageConfiguration(configPath, mapper, configFile)) );
-
- this.setDataTypeMappingProvider(new JavaDataTypeMappingProvider());
- this.setNameGenerator(new CamelCaseNamingPolicyProvider());
}
public LibraryCodeGenerator(String apiServerURL, String apiKey, String modelPackageName, String apiPackageName,
String classOutputDir, String libraryHome){
-
+ initialize(apiServerURL, apiKey, modelPackageName, apiPackageName, classOutputDir, libraryHome);
+ }
+
+ protected void initialize(String apiServerURL, String apiKey, String modelPackageName, String apiPackageName,
+ String classOutputDir, String libraryHome){
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ApiConfiguration aApiConfiguration = new ApiConfiguration();
@@ -88,11 +93,8 @@ public class LibraryCodeGenerator {
aLanguageConfiguration.setLibraryHome(libraryHome);
initializeLangConfig(aLanguageConfiguration);
this.setLanguageConfig(aLanguageConfiguration);
-
- this.setDataTypeMappingProvider(new JavaDataTypeMappingProvider());
- this.setNameGenerator(new CamelCaseNamingPolicyProvider());
}
-
+
/**
* Generate classes needed for the model and API invocation
*/
@@ -354,7 +356,7 @@ public class LibraryCodeGenerator {
template.setAttribute("extends", config.getServiceBaseClass(className));
File aFile = new File(languageConfig.getResourceClassLocation()+ resource.generateClassName(nameGenerator) +languageConfig.getClassFileExtension());
- writeFile(aFile, template.toString(), "API CLasses");
+ writeFile(aFile, template.toString(), "API Classes");
}catch(RuntimeException t){
System.out.println("Failed generating api class for the resource : " + resource.getResourcePath());
throw t;
diff --git a/src/main/java/com/wordnik/swagger/codegen/ResourceMethod.java b/src/main/java/com/wordnik/swagger/codegen/ResourceMethod.java
index b7d7a022dcb..87de5aabc7b 100644
--- a/src/main/java/com/wordnik/swagger/codegen/ResourceMethod.java
+++ b/src/main/java/com/wordnik/swagger/codegen/ResourceMethod.java
@@ -55,6 +55,16 @@ public class ResourceMethod {
private Model inputModel;
private Model listWrapperModel;
+
+ private boolean hasResponseValue;
+
+ public boolean isHasResponseValue(){
+ return hasResponseValue;
+ }
+
+ public void setHasResponseValue(boolean hasResponseValue){
+ this.hasResponseValue = hasResponseValue;
+ }
public String getTitle() {
return title;
diff --git a/src/main/java/com/wordnik/swagger/codegen/config/DataTypeMappingProvider.java b/src/main/java/com/wordnik/swagger/codegen/config/DataTypeMappingProvider.java
index db7ddc3d3f7..7f3efc9eaae 100644
--- a/src/main/java/com/wordnik/swagger/codegen/config/DataTypeMappingProvider.java
+++ b/src/main/java/com/wordnik/swagger/codegen/config/DataTypeMappingProvider.java
@@ -103,6 +103,17 @@ public interface DataTypeMappingProvider {
*/
public String generateSetInitialization(String typeClass);
+ /**
+ * Sets variable initialization.
+ *
+ * Example: In scala initializing a variable with an unknown value will be:
+ *
+ * var age:String = _
+ *
+ * @return
+ */
+ public String generateVariableInitialization(String typeClass);
+
/**
* Gets list of items that needs to be included when referring list objects in model or resource classes.
*
diff --git a/src/main/java/com/wordnik/swagger/codegen/config/as3/As3DataTypeMappingProvider.java b/src/main/java/com/wordnik/swagger/codegen/config/as3/As3DataTypeMappingProvider.java
index 045749d6833..216bc7a6252 100644
--- a/src/main/java/com/wordnik/swagger/codegen/config/as3/As3DataTypeMappingProvider.java
+++ b/src/main/java/com/wordnik/swagger/codegen/config/as3/As3DataTypeMappingProvider.java
@@ -182,4 +182,9 @@ public class As3DataTypeMappingProvider implements DataTypeMappingProvider {
}
return classShortName;
}
+
+ @Override
+ public String generateVariableInitialization(String typeClass) {
+ return "";
+ }
}
diff --git a/src/main/java/com/wordnik/swagger/codegen/config/java/JavaDataTypeMappingProvider.java b/src/main/java/com/wordnik/swagger/codegen/config/java/JavaDataTypeMappingProvider.java
index bd0eafd351e..a9dd41d9625 100644
--- a/src/main/java/com/wordnik/swagger/codegen/config/java/JavaDataTypeMappingProvider.java
+++ b/src/main/java/com/wordnik/swagger/codegen/config/java/JavaDataTypeMappingProvider.java
@@ -217,4 +217,9 @@ public class JavaDataTypeMappingProvider implements DataTypeMappingProvider {
return nameGenerator.applyClassNamingPolicy(type);
}
}
+
+ @Override
+ public String generateVariableInitialization(String typeClass) {
+ return "";
+ }
}
diff --git a/src/main/java/com/wordnik/swagger/codegen/config/scala/ScalaDataTypeMappingProvider.scala b/src/main/java/com/wordnik/swagger/codegen/config/scala/ScalaDataTypeMappingProvider.scala
new file mode 100644
index 00000000000..28724cb93a1
--- /dev/null
+++ b/src/main/java/com/wordnik/swagger/codegen/config/scala/ScalaDataTypeMappingProvider.scala
@@ -0,0 +1,200 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.codegen.config.scala
+
+import com.wordnik.swagger.codegen.config.DataTypeMappingProvider
+
+import com.wordnik.swagger.codegen.config.NamingPolicyProvider
+import com.wordnik.swagger.codegen.config.common.CamelCaseNamingPolicyProvider
+
+import scala.collection.mutable._
+import scala.collection.JavaConversions._
+
+object ScalaDataTypeMappingProvider {
+ val primitiveValueMap = Map("string" -> "String",
+ "String" -> "String",
+ "int" -> "int",
+ "integer" -> "int",
+ "Integer" -> "int",
+ "boolean" -> "boolean",
+ "Boolean" -> "boolean",
+ "long" -> "long",
+ "Long" -> "long",
+ "float" -> "float",
+ "Float" -> "float",
+ "Date" -> "Date",
+ "date" -> "Date")
+
+ val primitiveObjectMap = Map("string" -> "String",
+ "String" -> "String",
+ "java.lang.String" -> "String",
+ "int" -> "Integer",
+ "integer" -> "Integer",
+ "Integer" -> "Integer",
+ "java.lang.Integer" -> "Integer",
+ "boolean" -> "Boolean",
+ "Boolean" -> "Boolean",
+ "java.lang.Boolean" -> "Boolean",
+ "long" -> "Long",
+ "Long" -> "Long",
+ "java.lang.Long" -> "Long",
+ "float" -> "Float",
+ "Float" -> "Float",
+ "java.lang.Float" -> "Float",
+ "Date" -> "Date",
+ "date" -> "Date",
+ "java.util.Date" -> "Date")
+}
+
+class ScalaDataTypeMappingProvider extends DataTypeMappingProvider {
+ val nameGenerator = new CamelCaseNamingPolicyProvider()
+
+ def isPrimitiveType(input: String): Boolean = {
+ ScalaDataTypeMappingProvider.primitiveObjectMap.contains(input) match {
+ case true => true
+ case _ => false
+ }
+ }
+
+ def getListReturnTypeSignature(typeClass: String): String = {
+ return "List[" + nameGenerator.applyClassNamingPolicy(typeClass) + "]";
+ }
+
+ def getMapReturnTypeSignature(typeClass: String): String = {
+ return "Map[" + nameGenerator.applyClassNamingPolicy(typeClass) + "]";
+ }
+
+ def getSetReturnTypeSignature(typeClass: String): String = {
+ return "Set[" + nameGenerator.applyClassNamingPolicy(typeClass) + "]";
+ }
+
+ def generateVariableInitialization(typeClass:String):String = "=_"
+
+ def generateListInitialization(typeClass: String): String = {
+ return " new ListBuffer[" + nameGenerator.applyClassNamingPolicy(typeClass) + "]";
+ }
+
+ def generateMapInitialization(typeClass: String): String = {
+ return " new HashMap[" + nameGenerator.applyClassNamingPolicy(typeClass) + "]";
+ }
+
+ def generateSetInitialization(typeClass: String): String = {
+ return " new HashSet[" + nameGenerator.applyClassNamingPolicy(typeClass) + "]";
+ }
+
+ def getListIncludes(): java.util.List[String] = {
+ List("scala.collection.mutable.ListBuffer")
+ }
+
+ def getMapIncludes(): java.util.List[String] = {
+ List("java.util.Map", "java.util.HashMap")
+ }
+
+ def getSetIncludes: java.util.List[String] = {
+ List("java.util.Set", "java.util.HashSet")
+ }
+
+ def getDateIncludes: java.util.List[String] = {
+ List("java.util.Date")
+ }
+
+ /**
+ * Gets the short name of the class the class.
+ * Input can be MAP, LIST or regular string. In case of map or list the class name will be class name
+ * that map or list is returning.
+ * @param type
+ * @return
+ */
+ def getGenericType(inputType: String): String = {
+ var classShortName = ""
+ if (inputType.startsWith("List[")) {
+ classShortName = inputType.substring(5, inputType.length() - 1);
+ classShortName = getClassType(classShortName, true);
+ } else if (inputType.startsWith("Map[")) {
+ classShortName = inputType.substring(4, inputType.length() - 1)
+ classShortName = getClassType(classShortName, true)
+ } else if (inputType.startsWith("Set[")) {
+ classShortName = inputType.substring(4, inputType.length() - 1)
+ classShortName = getClassType(classShortName, true)
+ } else if (inputType.equalsIgnoreCase("ok")) {
+ classShortName = ""
+ } else {
+ classShortName = getClassType(inputType, true)
+ }
+ classShortName
+ }
+
+ /**
+ * Returns the syntax for defintion of an object of type and name
+ *
+ * @param argumentType
+ * @param argumentName
+ * @return
+ */
+ def getArgumentDefinition(argumentType: String, argumentName: String): String = {
+ argumentName + ":" + argumentType
+ }
+
+ /**
+ * Gets the class of the expected return value for a type string. Examples of type Strings are int, User, List[User]
+ * If the type string is a collection type like a map or list the string value returned would be the class
+ * that map or list is returning.
+ *
+ * @param type
+ * @return
+ */
+ def getClassType(input: String, primitiveObject: Boolean): String = {
+ if (input.equalsIgnoreCase("void") || input.equalsIgnoreCase("ok")) {
+ ""
+ } else {
+ var classShortName = ""
+ if (input.startsWith("List[")) {
+ classShortName = input.substring(5, input.length() - 1);
+ classShortName = "List[" + getClassName(classShortName, true) + "]";
+ } else if (input.startsWith("Map[")) {
+ classShortName = input.substring(4, input.length() - 1);
+ classShortName = "Map[" + getClassName(classShortName, true) + "]";
+ } else if (input.startsWith("Set[")) {
+ classShortName = input.substring(4, input.length() - 1);
+ classShortName = "Set[" + getClassName(classShortName, true) + "]";
+ } else {
+ classShortName = getClassName(input, true);
+ }
+ classShortName
+ }
+ }
+
+ /**
+ * If the data type is primitive and it is expecting object structure then return primitive objects
+ * else return primitive types
+ * @param type
+ * @param primitiveObject -- indicates if the object is primitive or not
+ * @return
+ */
+ def getClassName(input: String, primitiveObject: Boolean): String = {
+ isPrimitiveType(input) match {
+ case true => {
+ if (primitiveObject) {
+ ScalaDataTypeMappingProvider.primitiveObjectMap(input)
+ } else {
+ ScalaDataTypeMappingProvider.primitiveValueMap(input)
+ }
+ }
+ case _ => nameGenerator.applyClassNamingPolicy(input)
+ }
+ }
+}
diff --git a/src/main/java/com/wordnik/swagger/codegen/config/scala/ScalaLibCodeGen.scala b/src/main/java/com/wordnik/swagger/codegen/config/scala/ScalaLibCodeGen.scala
new file mode 100644
index 00000000000..cf10db75ba1
--- /dev/null
+++ b/src/main/java/com/wordnik/swagger/codegen/config/scala/ScalaLibCodeGen.scala
@@ -0,0 +1,93 @@
+/**
+ * Copyright 2011 Wordnik, 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.
+ */
+
+package com.wordnik.swagger.codegen.config.scala
+
+import com.wordnik.swagger.codegen.LibraryCodeGenerator
+import com.wordnik.swagger.codegen.config.LanguageConfiguration
+import com.wordnik.swagger.codegen.config.common.CamelCaseNamingPolicyProvider
+import com.wordnik.swagger.codegen.exception.CodeGenerationException
+import com.wordnik.swagger.codegen.util.FileUtil
+
+import java.io.File
+
+object ScalaLibCodeGen {
+ def main(args: Array[String]) = {
+ val codeGenerator = args.length match {
+ case 1 => new ScalaLibCodeGen(args(0))
+ case 4 => {
+ var apiServerURL = args(0)
+ if (!apiServerURL.endsWith("/")) {
+ apiServerURL = apiServerURL + "/"
+ }
+ val apiKey = args(1);
+ val packageName = args(2)
+ var libraryHome = args(3)
+ if (libraryHome.endsWith("/")) {
+ libraryHome = libraryHome.substring(0, libraryHome.length() - 1)
+ }
+ val modelPackageName = packageName + ".model"
+ val apiPackageName = packageName + ".api"
+ val classOutputDir = libraryHome + "/src/main/scala/" + packageName.replace(".", "/")
+ new ScalaLibCodeGen(apiServerURL, apiKey, modelPackageName, apiPackageName, classOutputDir, libraryHome)
+ }
+ case _ => throw new CodeGenerationException("Invalid number of arguments passed: No command line argument was passed to the program for config json")
+ }
+ codeGenerator.generateCode()
+ }
+}
+
+class ScalaLibCodeGen(
+ apiServerURL: String,
+ apiKey: String,
+ modelPackageName: String,
+ apiPackageName: String,
+ classOutputDir: String,
+ libraryHome: String,
+ configPath: String) extends LibraryCodeGenerator {
+
+ if (null != configPath) {
+ initializeWithConfigPath(configPath)
+ this.setDataTypeMappingProvider(new ScalaDataTypeMappingProvider())
+ this.setNameGenerator(new CamelCaseNamingPolicyProvider())
+ }
+ else{
+ initialize(apiServerURL, apiKey, modelPackageName, apiPackageName, classOutputDir, libraryHome)
+ setDataTypeMappingProvider(new ScalaDataTypeMappingProvider())
+ setNameGenerator(new CamelCaseNamingPolicyProvider())
+ }
+
+ def this(apiServerURL: String, apiKey: String, modelPackageName: String, apiPackageName: String, classOutputDir: String, libraryHome: String) = this(apiServerURL, apiKey, modelPackageName, apiPackageName, classOutputDir, libraryHome, null)
+ def this(configPath: String) = this(null, null, null, null, null, null, configPath)
+
+ override def initializeLangConfig(config: LanguageConfiguration): LanguageConfiguration = {
+ config.setClassFileExtension(".scala");
+ config.setTemplateLocation("conf/scala/templates");
+ config.setStructureLocation("conf/scala/structure");
+ config.setExceptionPackageName("com.wordnik.swagger.exception");
+ config.setAnnotationPackageName("com.wordnik.swagger.annotations");
+
+ //create ouput directories
+ FileUtil.createOutputDirectories(config.getModelClassLocation(), config.getClassFileExtension());
+ FileUtil.createOutputDirectories(config.getResourceClassLocation(), config.getClassFileExtension());
+ FileUtil.clearFolder(config.getModelClassLocation());
+ FileUtil.clearFolder(config.getResourceClassLocation());
+ FileUtil.clearFolder(config.getLibraryHome() + "/src/main/java/com/wordnik/swagger/runtime");
+ FileUtil.createOutputDirectories(config.getLibraryHome() + "/src/main/java/com/wordnik/swagger/runtime", "java");
+ FileUtil.copyDirectory(new File("src/main/java/com/wordnik/swagger/runtime"), new File(config.getLibraryHome() + "/src/main/java/com/wordnik/swagger/runtime"));
+ config
+ }
+}
diff --git a/src/main/java/com/wordnik/swagger/codegen/resource/EndpointOperation.java b/src/main/java/com/wordnik/swagger/codegen/resource/EndpointOperation.java
index 9846857edaa..829e737687c 100644
--- a/src/main/java/com/wordnik/swagger/codegen/resource/EndpointOperation.java
+++ b/src/main/java/com/wordnik/swagger/codegen/resource/EndpointOperation.java
@@ -303,6 +303,13 @@ public class EndpointOperation {
method.setMethodType(this.getHttpMethod());
//get return value
+ String returnType = dataTypeMapper.getClassType(responseClass, false);
+ if("".equals(returnType)){
+ method.setHasResponseValue(false);
+ }
+ else{
+ method.setHasResponseValue(true);
+ }
method.setReturnValue(dataTypeMapper.getClassType(responseClass, false));
method.setReturnClassName(dataTypeMapper.getGenericType(responseClass));
diff --git a/src/main/java/com/wordnik/swagger/codegen/resource/ModelField.java b/src/main/java/com/wordnik/swagger/codegen/resource/ModelField.java
index 89a32176525..1ae88672136 100644
--- a/src/main/java/com/wordnik/swagger/codegen/resource/ModelField.java
+++ b/src/main/java/com/wordnik/swagger/codegen/resource/ModelField.java
@@ -229,10 +229,10 @@ public class ModelField {
fieldDefinition.setName(this.getName());
}
}else{
+ fieldDefinition.setInitialization(dataTypeMapper.generateVariableInitialization(type));
fieldDefinition.setReturnType(dataTypeMapper.getClassType(type, false));
fieldDefinition.setName(this.getName());
}
-
}
return fieldDefinition;
}