package gargl.generators; import gargl.typedefinitions.Function; import gargl.utilities.Parameter; import java.util.Set; import java.util.List; import java.util.Map; public class JavascriptModuleGenerator extends Generator { private static final String JAVASCRIPT_REQUEST_STRING_CONCAT_FORMAT = " + \"%1$s\" + \"=\" + encodeURIComponent(%2$s) + \"&\""; private static String JAVASCRIPT_STRING_VARIABLE_DECLARATION_FORMAT = "\tvar %1$s = '%2$s';\n\n"; private static String JAVASCRIPT_CODE_VARIABLE_DECLARATION_FORMAT = "\tvar %1$s = %2$s;\n\n"; private static String JAVASCRIPT_KEYVALUE_FORMAT = "\t\t\"%1$s\": %2$s,\n"; private static String JAVASCRIPT_KEYVALUE_FORMAT2 = "\n\t\t\t%1$s: %2$s,"; private static String JAVASCRIPT_MODULE_FORMAT = "// This module requires jQuery. In Node.JS, jsdom and xmlhttprequest are also required.\n\n" + "try {\n" + "\t// Enable module to work with jQuery in Node.JS\n" + "\tvar jsdom = require('jsdom');\n" + "\tvar window = jsdom.jsdom().createWindow();\n" + "\tvar XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;\n\n" + "\tvar $ = require('jquery')(window);\n" + "\t$.support.cors = true;\n" + "\t$.ajaxSettings.xhr = function() {\n" + "\t\treturn new XMLHttpRequest;\n" + "\t}\n" + "}\n" + "catch(e) {\n" + "\tconsole.log(e);\n" + "}\n\n" + "var %1$s = {};\n\n" + "%2$s\n"; private static String JAVASCRIPT_FUNCTION_FORMAT = "\n%1$s.%2$s = function %3$s {\n%4$s" + "\n};\n" + "if(typeof(exports) != \"undefined\") exports.%2$s = %1$s.%2$s; // For nodeJS\n"; private static String JAVASCRIPT_GET_RESPONSE_FIELD = "\t\t\tvar _%1$s = $html.find('%2$s');\n"; private static String JAVASCRIPT_XHR_FORMAT = "\t$.ajax({\n" + "\t\ttype: type,\n" + "\t\turl: url,\n" + "\t\theaders: headers,\n" + "\t\tdata: data,\n" + "\t\tbeforeSend: function(xmlHttpRequest) {\n" + "\t\t\t// Requires node-XMLHttpRequest version 1.5.1 or later to set some headers in Node.js\n" + "\t\t\tif(xmlHttpRequest.setDisableHeaderCheck) xmlHttpRequest.setDisableHeaderCheck(true);\n" + "\t\t\treturn true;\n" + "\t\t}\n" + "\t})\n" + "\t.always(\n" + "\t\tfunction (response, error) {\n" + "\t\t\tresponse = response || '';\n\n" + "\t\t\tif (!response.responseText) {\n" + "\t\t\t\ttry {\n" + "\t\t\t\t\tvar $html = $(toStaticHTML(response));\n" + "\t\t\t\t}\n" + "\t\t\t\tcatch(e) {\n" + "\t\t\t\t\tvar $html = $(response);\n" + "\t\t\t\t}\n" + "\t\t\t}\n" + "\t\t\telse response = response.responseText;\n" + "%1$s\n" + "\t\t\tvar fullResponse = {\n" + "\t\t\t\tresponse: response," + "%2$s\n" + "\t\t\t};\n\n" + "\t\t\tcallback(null, fullResponse);\n\n" + "\t\t}\n" + "\t);"; public String generateFunction(String moduleName, Function function) { StringBuilder parametersSB = new StringBuilder("("); for(Parameter parameter : function.getParameters()) { parametersSB.append(parameter.getParameterName()); parametersSB.append(", "); } parametersSB.append("callback)"); StringBuilder functionBodySB = new StringBuilder(""); functionBodySB.append(String.format(JAVASCRIPT_STRING_VARIABLE_DECLARATION_FORMAT, "type", function.getMethod())); Map<String,String> headers = function.getHeaders(); StringBuilder headersStringSB = new StringBuilder("{\n"); for(String headerKey : headers.keySet()) { headersStringSB.append(String.format(JAVASCRIPT_KEYVALUE_FORMAT, headerKey, Parameter.processParameter(headers.get(headerKey).replace("\"","\\\""), function))); } headersStringSB.append("\t}"); functionBodySB.append(String.format(JAVASCRIPT_CODE_VARIABLE_DECLARATION_FORMAT, "headers", headersStringSB.toString())); Map<String,String> queryString = function.getQueryString(); StringBuilder queryStringSB = new StringBuilder("\"?\""); for(String queryStringKey : queryString.keySet()) { queryStringSB.append(String.format(JAVASCRIPT_REQUEST_STRING_CONCAT_FORMAT, queryStringKey, Parameter.processParameter(queryString.get(queryStringKey).replace("\"","\\\""), function))); } functionBodySB.append(String.format(JAVASCRIPT_CODE_VARIABLE_DECLARATION_FORMAT, "queryString", queryStringSB.toString())); Map<String,String> postData = function.getPostData(); StringBuilder postDataSB = new StringBuilder("\"\""); for(String postDataKey : postData.keySet()) { postDataSB.append(String.format(JAVASCRIPT_REQUEST_STRING_CONCAT_FORMAT, postDataKey, Parameter.processParameter(postData.get(postDataKey).replace("\"","\\\""), function))); } functionBodySB.append(String.format(JAVASCRIPT_CODE_VARIABLE_DECLARATION_FORMAT, "data", postDataSB.toString())); List<String> urlParts = Parameter.processURLParameters(function.getUrl(), function); StringBuilder urlStringSB = new StringBuilder(); for(String urlPart : urlParts) { urlStringSB.append(urlPart); urlStringSB.append(" + "); } urlStringSB.append("queryString"); functionBodySB.append(String.format(JAVASCRIPT_CODE_VARIABLE_DECLARATION_FORMAT, "url", urlStringSB.toString())); StringBuilder responseFieldsGrabSB = new StringBuilder(); StringBuilder responseFieldsSB = new StringBuilder(); Map<String,String> responseFields = function.getResponseFields(); for(String responseName : responseFields.keySet()) { responseFieldsGrabSB.append(String.format(JAVASCRIPT_GET_RESPONSE_FIELD, responseName, responseFields.get(responseName))); responseFieldsSB.append(String.format(JAVASCRIPT_KEYVALUE_FORMAT2, "\t" + responseName, "_" + responseName)); } functionBodySB.append(String.format(JAVASCRIPT_XHR_FORMAT, responseFieldsGrabSB.toString(), responseFieldsSB.toString())); return String.format(JAVASCRIPT_FUNCTION_FORMAT, moduleName, function.getFunctionName(), parametersSB.toString(), functionBodySB.toString()); } @Override public void generateClass(String outputLocation) { String moduleName = this.module.name; if(this.module.name == null || this.module.name.isEmpty()){ moduleName = "gargl_output"; System.out.println("WARNING: No module name given, module name defaulting to " + moduleName); } StringBuilder functionsSB = new StringBuilder(); for (Function function : this.module.functions) { functionsSB.append(generateFunction(moduleName, function)); System.out.println("LOG: Function " + function.getFunctionName() + " created"); } // File name is currently forced to be the same as module name writeFile(outputLocation + moduleName + ".js", String.format(JAVASCRIPT_MODULE_FORMAT, moduleName, functionsSB.toString())); } }