package org.lazydoc.printer; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.lazydoc.config.PrinterConfig; import org.lazydoc.model.*; import java.io.File; import java.io.IOException; import java.util.*; import static org.apache.commons.lang3.StringUtils.join; public class SwaggerDocumentationPrinter extends DocumentationPrinter { // TODO update SwaggerDocumentationPrinter private Set<String> models = new HashSet<>(); @Override public void print(PrinterConfig printerConfig) throws Exception { this.printerConfig = printerConfig; printSwaggerToJsp(); } private String getDataTypeFilename(String name) { return "api/_types/" + name.toLowerCase() + ".jsp"; } private void printSwaggerToJsp() throws Exception { addDomainsAndDataTypesToFilelist(); createDiscover(); createAndWriteViewController(); writeFiles(FilenameUtils.normalize(printerConfig.getOutputPath())); } private void addDomainsAndDataTypesToFilelist() { for (DocDomain domain : printerConfig.getDomains().values()) { if (domain.getSubDomains().isEmpty()) { files.put("api/" + domain.getDomain().toLowerCase() + ".jsp", printDomainToJson(domain)); } else { for (DocSubDomain subDomain : domain.getSubDomains().values()) { files.put("api/" + (domain.getDomain() + "-" + subDomain.getSubDomain()).toLowerCase() + ".jsp", printDomainToJson(subDomain)); } } } for (DocDataType dataType : printerConfig.getDataTypes().values()) { files.put(getDataTypeFilename(dataType.getName()), printDataTypeToJson(dataType)); } } public String printDomainToJson(DocDomain domain) { return printDomainOrSubDomainToJson(domain.getOperations(), domain.getDomain()); } public String printSubDomainToJson(Map<String, String> files, DocSubDomain subDomain) { return printDomainOrSubDomainToJson(subDomain.getOperations(), subDomain.getDomain() + "-" + subDomain.getSubDomain()); } public String printDomainOrSubDomainToJson(Set<DocOperation> docOperations, String domainName) { models.clear(); String basePath = printerConfig.getParams().get("swagger.basepath"); if(StringUtils.isBlank(basePath)) { throw new RuntimeException("Please provide the swagger.basepath in the printer config params"); } String json = "<%@ page contentType=\"application/json; charset=UTF-8\" %>\n"; json += "{\n"; json += " \"basePath\": \"" + basePath + "\",\n"; json += " \"apis\": [\n"; List<String> apis = new ArrayList<String>(); for (DocOperation operation : docOperations) { apis.add(printApiOperationToJson(domainName, operation)); } json += join(apis, ",\n"); json += " ],\n"; json += " \"models\": {\n"; json += StringUtils.join(models, ","); json += " }\n"; json += "}\n"; return json; } public String printApiOperationToJson(String domainName, DocOperation operation) { operation.setFileName("api/_ops/" + domainName + "/" + operation.getNickname() + ".jsp"); String json = " {\n"; json += " \"path\": \"" + operation.getPath() + "\",\n"; json += " \"description\": \"" + operation.getShortDescription() + "\",\n"; json += " \"operations\": [\n"; json += " <%@include file=\"" + operation.getFileName().replaceAll("api/", "") + "\" %>"; json += " ]\n"; json += " }"; files.put(operation.getFileName(), printOperationToJson(operation)); return json; } public String printOperationToJson(DocOperation operation) { List<String> parameters = new ArrayList<String>(); String json = "{\n"; json += " \"method\": \"" + operation.getHttpMethod() + "\",\n"; json += " \"nickname\": \"" + operation.getNickname() + "\",\n"; json += " \"responseClass\": \"" + getOperationResponse(operation.getOperationResponse()) + "\",\n"; json += " \"parameters\": [\n"; for (DocParameter parameter : operation.getParameters()) { parameters.add(" <%@include file=\"../../_params/" + parameter.getReferenceName() + ".jsp\" %>"); files.put("api/_params/" + parameter.getReferenceName() + ".jsp", printParameterToJson(parameter)); } json += join(parameters, ",\n") + "\n"; json += " ],\n"; json += " \"summary\": \"" + operation.getShortDescription() + "\",\n"; json += " \"notes\": \"" + operation.getNotes() + "\",\n"; json += " \"authorization\": \"\",\n"; json += " \"errorResponses\": [],\n"; json += " \"level\": \"\"\n"; json += "}\n"; return json; } private String getOperationResponse(DocOperationResponse operationResponse) { if(operationResponse.isInList()) { return "List["+operationResponse.getResponseType()+"]"; } return operationResponse.getResponseType(); } public String printParameterToJson(DocParameter parameter) { String json = "{\n"; String paramType = parameter.getParamType(); json += " \"paramType\": \"" + paramType + "\",\n"; if (paramType.equals("body")) { json += " \"name\": \"requestBody\",\n"; } else { json += " \"name\": \"" + parameter.getName() + "\",\n"; } json += " \"description\": \"" + parameter.getDescription() + "\",\n"; json += " \"type\": \"" + parameter.getDataType() + "\",\n"; json += " \"required\": " + parameter.isRequired() + ",\n"; json += " \"allowMultiple\": " + parameter.isAllowMultiple() + ",\n"; json += " \"list\": " + parameter.isList() + "\n"; json += "}\n"; addModelOfParameter(parameter.getDataType()); return json; } private void addModelOfParameter(String dataType) { DocDataType docDataType = printerConfig.getDataTypes().get(dataType); if (docDataType != null) { models.add(" <%@include file=\"" + getDataTypeFilename(dataType).replaceAll("api/", "") + "\" %>"); for(DocProperty property : docDataType.getProperties()) { addModelOfParameter(property.getType()); } } } public String printDataTypeToJson(DocDataType dataType) { List<String> properties = new ArrayList<String>(); String json = "\"" + dataType.getName() + "\": {\n"; json += " \"properties\": {\n"; for (DocProperty property : dataType.getProperties()) { properties.add(printPropertyToJson(property)); } json += join(properties, ",\n") + "\n"; json += " }\n"; json += "}\n"; return json; } public String printPropertyToJson(DocProperty property) { String json = " \"" + property.getName() + "\": {\n"; if (property.isList()) { json += " \"type\": \"List[" + property.getType() + "]\",\n"; } else { json += " \"type\": \"" + property.getType() + "\",\n"; } if (property.hasEnumValues()) { json += " \"enum\": [\"" + property.getEnumValues() + "\"],\n"; } json += " \"description\": \"" + property.getDescription() + "\",\n"; if (property.hasSample()) { json += " \"sample\": " + property.getSampleString() + ",\n"; } json += " \"required\": " + property.isRequired() + ",\n"; json += " \"request\": " + property.isRequest() + ",\n"; json += " \"response\": " + property.isResponse() + ",\n"; json += " \"list\": " + property.isList() + "\n"; json += " }"; return json; } private void createAndWriteViewController() throws IOException { String viewPropertiesFilename = printerConfig.getParams().get("swagger.views.properties.filename"); String swaggerDirectoryName = printerConfig.getParams().get("swagger.directory.name"); if(StringUtils.isBlank(viewPropertiesFilename)) { throw new RuntimeException("Please provide the swagger.views.properties.filename in printer config params"); } if(StringUtils.isBlank(swaggerDirectoryName)) { throw new RuntimeException("Please provide the swagger.directory.name in printer config params"); } List<String> mvcViews = new ArrayList<String>(); for (DocDomain domain : printerConfig.getDomains().values()) { if (!domain.getOperations().isEmpty()) { addViewMapping(mvcViews, domain.getDomain(), swaggerDirectoryName); } for (DocSubDomain subDomain : domain.getSubDomains().values()) { addViewMapping(mvcViews, domain.getDomain()+"-"+subDomain.getSubDomain(), swaggerDirectoryName); } } File viewControllers = new File(viewPropertiesFilename); viewControllers.getParentFile().mkdirs(); FileUtils.writeLines(viewControllers, mvcViews); } private void addViewMapping(List<String> mvcViews, String domain, String swaggerDirectoryName) { mvcViews.add("/discover/" + StringUtils.capitalize(domain) + "=/" + swaggerDirectoryName + "/" + domain.toLowerCase()); } private void createDiscover() { List<String> apis = new ArrayList<String>(); for (DocDomain domain : printerConfig.getDomains().values()) { if (!domain.getOperations().isEmpty()) { apis.add(createApiPathJson(domain)); } for (DocSubDomain subDomain : domain.getSubDomains().values()) { apis.add(createApiPathJson(subDomain)); } } String json = "<%@ page contentType=\"application/json; charset=UTF-8\" %>\n"; json += "{\n"; json += " \"apis\":[\n"; json += join(apis, ",\n") + "\n"; json += " ]\n"; json += "}\n"; files.put("discover.jsp", json); } private String createApiPathJson(DocDomain domain) { String api = " {\n"; api += " \"path\": \"/" + StringUtils.capitalize(domain.getDomain()) + "\",\n"; api += " \"description\": \"" + domain.getDescription() + "\"\n"; api += " }"; return api; } }