From 0203e5d7d47dbfc12e9a4268347590d959db0706 Mon Sep 17 00:00:00 2001 From: anshu2185 Date: Wed, 22 Nov 2017 14:35:00 +0530 Subject: [PATCH 01/19] Added pkmst-microservice toolkit --- .../codegen/languages/PkmstServerCodegen.java | 1539 +++++++++++++++++ .../services/io.swagger.codegen.CodegenConfig | 1 + .../pkmst/RFC3339DateFormat.mustache | 20 + .../pkmst/SpringBootApplication.mustache | 36 + .../src/main/resources/pkmst/api.mustache | 87 + .../resources/pkmst/apiController.mustache | 115 ++ .../resources/pkmst/apiException.mustache | 10 + .../resources/pkmst/apiOriginFilter.mustache | 27 + .../pkmst/apiResponseMessage.mustache | 69 + .../src/main/resources/pkmst/api_doc.mustache | 82 + .../main/resources/pkmst/api_test.mustache | 57 + .../main/resources/pkmst/bodyParams.mustache | 1 + .../resources/pkmst/config/appconfig.mustache | 101 ++ .../pkmst/config/pkmstproperties.mustache | 113 ++ .../swaggerDocumentationConfig.mustache | 61 + .../pkmst/cucumber/cucumber.mustache | 33 + .../pkmst/cucumber/cucumberSteps.mustache | 76 + .../pkmst/cucumber/cucumberTest.mustache | 15 + .../pkmst/cucumber/executeReport.mustache | 42 + .../resources/pkmst/cucumber/package.mustache | 2 + .../src/main/resources/pkmst/docker.mustache | 3 + .../main/resources/pkmst/enumClass.mustache | 44 + .../pkmst/exampleReturnTypes.mustache | 1 + .../main/resources/pkmst/formParams.mustache | 1 + .../pkmst/gatling/application.mustache | 14 + .../resources/pkmst/gatling/gatling.mustache | 157 ++ .../resources/pkmst/gatling/package.mustache | 0 .../resources/pkmst/gatling/testapi.mustache | 41 + .../pkmst/generatedAnnotation.mustache | 3 + .../resources/pkmst/headerParams.mustache | 1 + .../integration/integrationtest.mustache | 34 + .../main/resources/pkmst/licenseInfo.mustache | 11 + .../pkmst/logging/httpLoggingFilter.mustache | 434 +++++ .../main/resources/pkmst/logstash.mustache | 35 + .../main/resources/pkmst/manifest.mustache | 12 + .../src/main/resources/pkmst/model.mustache | 37 + .../main/resources/pkmst/model_doc.mustache | 3 + .../pkmst/notFoundException.mustache | 10 + .../resources/pkmst/optionalDataType.mustache | 1 + .../main/resources/pkmst/pathParams.mustache | 1 + .../src/main/resources/pkmst/pojo.mustache | 140 ++ .../main/resources/pkmst/pojo_doc.mustache | 15 + .../src/main/resources/pkmst/pom.mustache | 442 +++++ .../main/resources/pkmst/queryParams.mustache | 1 + .../src/main/resources/pkmst/readme.mustache | 121 ++ .../resources/application-dev-config.mustache | 7 + .../pkmst/resources/application-dev.mustache | 78 + .../resources/application-local.mustache | 87 + .../pkmst/resources/application.mustache | 5 + .../pkmst/resources/bootstrap.mustache | 5 + .../main/resources/pkmst/returnTypes.mustache | 1 + .../authorizationServerConfiguration.mustache | 61 + .../oAuth2SecurityConfiguration.mustache | 82 + .../resourceServerConfiguration.mustache | 42 + .../testresources/application-test.mustache | 4 + .../pkmst/testresources/application.mustache | 4 + .../pkmst/testresources/bootstrap.mustache | 5 + .../resources/pkmst/xmlAnnotation.mustache | 6 + 58 files changed, 4436 insertions(+) create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/RFC3339DateFormat.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/SpringBootApplication.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/api.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/apiController.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/apiException.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/apiOriginFilter.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/apiResponseMessage.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/api_doc.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/api_test.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/bodyParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/config/appconfig.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/config/pkmstproperties.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/config/swaggerDocumentationConfig.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumber.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberSteps.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberTest.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/cucumber/executeReport.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/cucumber/package.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/docker.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/enumClass.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/exampleReturnTypes.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/formParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/gatling/application.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/gatling/gatling.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/gatling/package.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/gatling/testapi.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/generatedAnnotation.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/headerParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/integration/integrationtest.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/licenseInfo.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/logstash.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/manifest.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/model.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/model_doc.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/notFoundException.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/optionalDataType.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/pathParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/pojo.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/pojo_doc.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/pom.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/queryParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/readme.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev-config.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/resources/application-local.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/resources/application.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/resources/bootstrap.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/returnTypes.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/security/authorizationServerConfiguration.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/security/oAuth2SecurityConfiguration.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/security/resourceServerConfiguration.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/testresources/application-test.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/testresources/application.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/testresources/bootstrap.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/xmlAnnotation.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java new file mode 100644 index 00000000000..68cfff5d796 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java @@ -0,0 +1,1539 @@ +package io.swagger.codegen.languages; + + +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.ListIterator; +import java.util.Map; + +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; + +import io.swagger.codegen.CliOption; +import io.swagger.codegen.CodegenConfig; +import io.swagger.codegen.CodegenConstants; +import io.swagger.codegen.CodegenModel; +import io.swagger.codegen.CodegenOperation; +import io.swagger.codegen.CodegenParameter; +import io.swagger.codegen.CodegenProperty; +import io.swagger.codegen.CodegenResponse; +import io.swagger.codegen.CodegenType; +import io.swagger.codegen.DefaultCodegen; +import io.swagger.codegen.SupportingFile; +import io.swagger.models.Model; +import io.swagger.models.Operation; +import io.swagger.models.Path; +import io.swagger.models.Swagger; +import io.swagger.models.Tag; +import io.swagger.models.parameters.FormParameter; +import io.swagger.models.parameters.Parameter; +import io.swagger.models.properties.ArrayProperty; +import io.swagger.models.properties.BooleanProperty; +import io.swagger.models.properties.DoubleProperty; +import io.swagger.models.properties.FloatProperty; +import io.swagger.models.properties.IntegerProperty; +import io.swagger.models.properties.LongProperty; +import io.swagger.models.properties.MapProperty; +import io.swagger.models.properties.Property; +import io.swagger.models.properties.StringProperty; + +/** + * Created by prokarma on 04/09/17. + */ +public class PkmstServerCodegen extends DefaultCodegen implements CodegenConfig { + + public static final String FULL_JAVA_UTIL = "fullJavaUtil"; + public static final String SUPPORT_JAVA6 = "supportJava6"; + public static final String CONFIG_PACKAGE = "configPackage"; + public static final String BASE_PACKAGE = "basePackage"; + public static final String TITLE = "title"; + public static final String WITH_XML = "withXml"; + public static final String EUREKA_URI = "eurekaUri"; + public static final String ZIPKIN_URI = "zipkinUri"; + public static final String SPRINGADMIN_URI = "springBootAdminUri"; + protected String groupId = "com.prokarma"; + protected String artifactId = "pkmst-microservice"; + protected String artifactVersion = "1.0.0"; + protected String projectFolder; + + +protected String projectTestFolder; + protected String sourceFolder; + protected String testFolder; + protected String basePackage = "com.prokarma.pkmst"; + protected String serviceName = "Pkmst"; + protected String configPackage = "com.prokarma.pkmst.config"; + protected boolean implicitHeaders = false; + protected boolean serializeBigDecimalAsString = false; + protected boolean withXml = false; + protected boolean fullJavaUtil; + protected String javaUtilPrefix = ""; + protected Boolean serializableModel = false; + protected String invokerPackage; + protected String title; + protected String apiDocPath = "docs/"; + protected String modelDocPath = "docs/"; + protected String eurekaUri; + protected String zipkinUri; + protected String springBootAdminUri; + + public PkmstServerCodegen() { + super(); + this.projectFolder = "src" + File.separator + "main"; + this.projectTestFolder = "src" + File.separator + "test"; + this.sourceFolder = this.projectFolder + File.separator + "java"; + this.testFolder = this.projectTestFolder + File.separator + "java"; + embeddedTemplateDir = templateDir = "pkmst"; + apiPackage = "com.prokarma.pkmst.controller"; + modelPackage = "com.prokarma.pkmst.model"; + invokerPackage = "com.prokarma.pkmst.controller"; + setReservedWordsLowerCase( + Arrays.asList( + // used as internal variables, can collide with parameter names + "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", + "localVarHeaderParams", "localVarFormParams", "localVarPostBody", + "localVarAccepts", "localVarAccept", "localVarContentTypes", + "localVarContentType", "localVarAuthNames", "localReturnType", + "ApiClient", "ApiException", "ApiResponse", "Configuration", "StringUtil", + + // language reserved words + "abstract", "continue", "for", "new", "switch", "assert", + "default", "if", "package", "synchronized", "boolean", "do", "goto", "private", + "this", "break", "double", "implements", "protected", "throw", "byte", "else", + "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", + "void", "class", "finally", "long", "strictfp", "volatile", "const", "float", + "native", "super", "while", "null") + ); + + this.languageSpecificPrimitives = new HashSet( + Arrays.asList( + "String", + "boolean", + "Boolean", + "Double", + "Integer", + "Long", + "Float", + "Object", + "byte[]") + ); + this.instantiationTypes.put("array", "ArrayList"); + this.instantiationTypes.put("map", "HashMap"); + this.typeMapping.put("date", "Date"); + this.typeMapping.put("file", "File"); + + this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); + this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); + this.cliOptions.add(new CliOption("serviceName", "Service Name")); + this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); + this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); + this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); + this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); + //Middleware config + this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); + this.apiTestTemplateFiles.put("api_test.mustache", ".java"); + this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); + this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); + } + + private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, + CodegenModel parentCodegenModel) { + // This generator uses inline classes to define enums, which breaks when + // dealing with models that have subTypes. To clean this up, we will analyze + // the parent and child models, look for enums that match, and remove + // them from the child models and leave them in the parent. + // Because the child models extend the parents, the enums will be available via the parent. + + // Only bother with reconciliation if the parent model has enums. + if (!parentCodegenModel.hasEnums) { + return codegenModel; + } + + // Get the properties for the parent and child models + final List parentModelCodegenProperties = parentCodegenModel.vars; + List codegenProperties = codegenModel.vars; + + // Iterate over all of the parent model properties + boolean removedChildEnum = false; + for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { + // Look for enums + if (parentModelCodegenPropery.isEnum) { + // Now that we have found an enum in the parent class, + // and search the child class for the same enum. + Iterator iterator = codegenProperties.iterator(); + while (iterator.hasNext()) { + CodegenProperty codegenProperty = iterator.next(); + if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { + // We found an enum in the child class that is + // a duplicate of the one in the parent, so remove it. + iterator.remove(); + removedChildEnum = true; + } + } + } + } + + if (removedChildEnum) { + // If we removed an entry from this model's vars, we need to ensure hasMore is updated + int count = 0, numVars = codegenProperties.size(); + for (CodegenProperty codegenProperty : codegenProperties) { + count += 1; + codegenProperty.hasMore = (count < numVars) ? true : false; + } + codegenModel.vars = codegenProperties; + } + return codegenModel; + } + + private static String getAccept(Operation operation) { + String accepts = null; + String defaultContentType = "application/json"; + if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String produces : operation.getProduces()) { + if (defaultContentType.equalsIgnoreCase(produces)) { + accepts = defaultContentType; + break; + } else { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(produces); + } + } + if (accepts == null) { + accepts = sb.toString(); + } + } else { + accepts = defaultContentType; + } + + return accepts; + } + + public CodegenType getTag() { + return CodegenType.SERVER; + } + + public String getName() { + return "pkmst"; + } + + public String getHelp() { + return "Generates a Java SpringBoot Server application using the SpringFox integration." + + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; + } + + public void processOpts() { + super.processOpts(); + if (this.additionalProperties.containsKey("basePackage")) { + this.setBasePackage((String) this.additionalProperties.get("basePackage")); + this.setInvokerPackage(this.getBasePackage()); + this.apiPackage = this.getBasePackage() + ".controller"; + this.modelPackage = this.getBasePackage() + ".model"; + this.setConfigPackage(this.getBasePackage() + ".config"); + + //this.additionalProperties.put(BASE_PACKAGE, this.getBasePackage()); + }else{ + this.additionalProperties.put(BASE_PACKAGE, basePackage); + this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); + this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); + this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); + this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + } + if (this.additionalProperties.containsKey("groupId")) { + this.setGroupId((String) this.additionalProperties.get("groupId")); + }else { + //not set, use to be passed to template + additionalProperties.put(CodegenConstants.GROUP_ID, groupId); + } + if (this.additionalProperties.containsKey("artifactId")) { + this.setArtifactId((String) this.additionalProperties.get("artifactId")); + }else { + //not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); + } + if (this.additionalProperties.containsKey("artifactVersion")) { + this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); + }else { + //not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + } + if (this.additionalProperties.containsKey("serviceName")) { + this.setServiceName((String) this.additionalProperties.get("serviceName")); + } + else { + //not set, use to be passed to template + additionalProperties.put("serviceName", serviceName); + } + + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { + this.setSerializeBigDecimalAsString(Boolean.valueOf( + this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING) + .toString())); + } + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { + this.setSerializableModel(Boolean + .valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); + } + if (this.additionalProperties.containsKey(TITLE)) { + this.setTitle((String) this.additionalProperties.get(TITLE)); + } + this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); + if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { + this.setFullJavaUtil( + Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); + } + + if (this.additionalProperties.containsKey(EUREKA_URI)) { + this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); + } + if (this.additionalProperties.containsKey(ZIPKIN_URI)) { + this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); + } + if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { + this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); + } + if (fullJavaUtil) { + javaUtilPrefix = "java.util."; + } + this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); + this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); + this.additionalProperties.put(SUPPORT_JAVA6, false); + this.additionalProperties.put("java8", true); + + if (this.additionalProperties.containsKey(WITH_XML)) { + this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); + } + this.additionalProperties.put(WITH_XML, withXml); + + // make api and model doc path available in mustache template + this.additionalProperties.put("apiDocPath", apiDocPath); + this.additionalProperties.put("modelDocPath", modelDocPath); + + this.importMapping.put("List", "java.util.List"); + + if (fullJavaUtil) { + this.typeMapping.put("array", "java.util.List"); + this.typeMapping.put("map", "java.util.Map"); + this.typeMapping.put("DateTime", "java.util.Date"); + this.typeMapping.put("UUID", "java.util.UUID"); + this.typeMapping.remove("List"); + this.importMapping.remove("Date"); + this.importMapping.remove("Map"); + this.importMapping.remove("HashMap"); + this.importMapping.remove("Array"); + this.importMapping.remove("ArrayList"); + this.importMapping.remove("List"); + this.importMapping.remove("Set"); + this.importMapping.remove("DateTime"); + this.importMapping.remove("UUID"); + this.instantiationTypes.put("array", "java.util.ArrayList"); + this.instantiationTypes.put("map", "java.util.HashMap"); + } + // optional jackson mappings for BigDecimal support + this.importMapping + .put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); + this.importMapping + .put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); + + // imports for pojos + this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); + this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); + this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); + this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); + this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); + this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); + this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); + this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); + this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); + this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); + this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); + this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); + this.importMapping.put("IOException", "java.io.IOException"); + this.importMapping.put("Objects", "java.util.Objects"); + this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); + // import JsonCreator if JsonProperty is imported + // used later in recursive import in postProcessingModels + this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", + "com.fasterxml.jackson.annotation.JsonCreator"); + + this.apiTemplateFiles.put("api.mustache", ".java"); + this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); + + this.modelTemplateFiles.put("model.mustache", ".java"); + + this.supportingFiles.add(new SupportingFile( + "SpringBootApplication.mustache", + (this.getSourceFolder() + File.separator + this.getBasePackage()) + .replace(".", File.separator), + this.getServiceName() + "Application" + ".java")); + + this.supportingFiles.add(new SupportingFile( + "config" + File.separator + "swaggerDocumentationConfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()) + .replace(".", java.io.File.separator) + File.separator + "swagger", + "SwaggerDocumentationConfig.java")); + + this.supportingFiles.add(new SupportingFile( + "config" + File.separator + "pkmstproperties.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()) + .replace(".", java.io.File.separator) + File.separator + "swagger", + "PkmstProperties.java")); + this.supportingFiles.add(new SupportingFile( + "config" + File.separator + "appconfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()) + .replace(".", java.io.File.separator) + File.separator, + "AppConfig.java")); + + // Security + this.supportingFiles.add(new SupportingFile( + "security" + File.separator + "authorizationServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "AuthorizationServerConfiguration.java" + )); + this.supportingFiles.add(new SupportingFile( + "security" + File.separator + "oAuth2SecurityConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "OAuth2SecurityConfiguration.java" + )); + this.supportingFiles.add(new SupportingFile( + "security" + File.separator + "resourceServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "ResourceServerConfiguration.java" + )); + + // logging + + this.supportingFiles.add(new SupportingFile( + "logging" + File.separator + "httpLoggingFilter.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "logging", + "HttpLoggingFilter.java" + )); + + // Resources + this.supportingFiles.add(new SupportingFile( + "resources" + File.separator + "application-local.mustache", + ("src.main.resources").replace(".", java.io.File.separator), + "application-local.yml")); + this.supportingFiles.add(new SupportingFile( + "resources" + File.separator + "application-dev.mustache", + ("src.main.resources").replace(".", java.io.File.separator), + "application-dev.yml")); + this.supportingFiles.add(new SupportingFile( + "resources" + File.separator + "application-dev-config.mustache", + ("src.main.resources").replace(".", java.io.File.separator), + "application-dev-config.yml")); + this.supportingFiles.add(new SupportingFile( + "resources" + File.separator + "bootstrap.mustache", + ("src.main.resources").replace(".", java.io.File.separator), + "bootstrap.yml")); + + // POM + this.supportingFiles.add(new SupportingFile( + "pom.mustache", + "", + "pom.xml")); + + //Readme + this.supportingFiles.add(new SupportingFile( + "readme.mustache", + "", + "Readme.md")); + + //manifest + + this.supportingFiles.add(new SupportingFile( + "manifest.mustache", + "", + "manifest.yml")); + + //docker + this.supportingFiles.add(new SupportingFile( + "docker.mustache", + "", + "Dockerfile")); + + //logstash + + this.supportingFiles.add(new SupportingFile( + "logstash.mustache", + "", + "logstash.conf")); + + // Cucumber + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "executeReport.mustache", + this.testFolder + File.separator + this.basePackage .replace(".", File.separator) + + File.separator +"cucumber" + File.separator+"report", + "ExecuteReport.java" + )); + + + + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberTest.mustache", + this.testFolder + File.separator + this.basePackage .replace(".", File.separator) + + File.separator +"cucumber", + serviceName + "Test.java" + )); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberSteps.mustache", + this.testFolder + File.separator + this.basePackage .replace(".", File.separator) + + File.separator +"cucumber", + serviceName + "Steps.java" + )); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "package.mustache", + this.testFolder + File.separator + this.basePackage .replace(".", File.separator) + + File.separator +"cucumber", + serviceName + "package-info.java" + )); + + //test resources + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumber.mustache", + (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "cucumber", + serviceName+".feature" + )); + + this.supportingFiles.add(new SupportingFile( + "testresources" + File.separator + "bootstrap.mustache", + ("src.test.resources").replace(".", java.io.File.separator), + "bootstrap.yml")); + this.supportingFiles.add(new SupportingFile( + "testresources" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), + "application.properties")); + this.supportingFiles.add(new SupportingFile( + "testresources" + File.separator + "application-test.mustache", + ("src.test.resources").replace(".", java.io.File.separator), + "application-test.properties")); + + //Gatling + this.supportingFiles.add(new SupportingFile( + "gatling" + File.separator + "gatling.mustache", + ("src.test.resources").replace(".", java.io.File.separator), + "gatling.conf")); + + + this.supportingFiles.add(new SupportingFile( + "gatling" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), + "application.conf")); + + this.supportingFiles.add(new SupportingFile( + "gatling" + File.separator + "testapi.mustache", + ("src")+ File.separator + ("test")+ File.separator + ("scala")+ File.separator + ("scalaFiles").replace(".", java.io.File.separator), + "testapi.scala")); + + /*this.supportingFiles.add(new SupportingFile( + "gatling" + File.separator + "package.mustache", + ("src")+ File.separator + ("test")+ File.separator + ("scala")+ File.separator + ("scalaFiles").replace(".", java.io.File.separator), + "package.info"));*/ + + // adding class for integration test + this.supportingFiles.add(new SupportingFile( + "integration" + File.separator + "integrationtest.mustache", + this.testFolder + File.separator + this.basePackage .replace(".", File.separator) + + File.separator +"controller", + serviceName + "IT.java" + )); + } + + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (final CodegenOperation operation : ops) { + List responses = operation.responses; + if (responses != null) { + for (final CodegenResponse resp : responses) { + if ("0".equals(resp.code)) { + resp.code = "200"; + } + doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + resp.dataType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + resp.containerType = returnContainer; + } + }); + } + } + + doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + operation.returnType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + operation.returnContainer = returnContainer; + } + }); + + if (implicitHeaders) { + removeHeadersFromAllParams(operation.allParams); + } + } + } + + return objs; + } + + /** + * This method removes header parameters from the list of parameters and also + * corrects last allParams hasMore state. + * + * @param allParams list of all parameters + */ + private void removeHeadersFromAllParams(List allParams) { + if (allParams.isEmpty()) { + return; + } + final ArrayList copy = new ArrayList(allParams); + allParams.clear(); + + for (CodegenParameter p : copy) { + if (!p.isHeaderParam) { + allParams.add(p); + } + } + allParams.get(allParams.size() - 1).hasMore = false; + } + + /** + * @param returnType The return type that needs to be converted + * @param dataTypeAssigner An object that will assign the data to the respective fields in the + * model. + */ + private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { + final String rt = returnType; + if (rt == null) { + dataTypeAssigner.setReturnType("Void"); + } else if (rt.startsWith("List")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("List"); + } + } else if (rt.startsWith("Map")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); + dataTypeAssigner.setReturnContainer("Map"); + } + } else if (rt.startsWith("Set")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("Set"); + } + } + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + + swaggerType = getAlias(swaggerType); + + // don't apply renaming on types from the typeMapping + if (this.typeMapping.containsKey(swaggerType)) { + return this.typeMapping.get(swaggerType); + } + + if (null == swaggerType) { + LOGGER.error("No Type defined for Property " + p); + } + return toModelName(swaggerType); + } + + @Override + public String getAlias(String name) { + if (typeAliases.containsKey(name)) { + return typeAliases.get(name); + } + return name; + } + + @Override + public String toModelName(final String name) { + // We need to check if import-mapping has a different model for this class, so we use it + // instead of the auto-generated one. + if (this.importMapping.containsKey(name)) { + return this.importMapping.get(name); + } + + final String sanitizedName = sanitizeName(name); + + String nameWithPrefixSuffix = sanitizedName; + if (!StringUtils.isEmpty(modelNamePrefix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; + } + + if (!StringUtils.isEmpty(modelNameSuffix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; + } + + // camelize the model name + // phone_number => PhoneNumber + final String camelizedName = camelize(nameWithPrefixSuffix); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(camelizedName)) { + final String modelName = "Model" + camelizedName; + LOGGER.warn( + camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); + return modelName; + } + + // model name starts with number + if (camelizedName.matches("^\\d.*")) { + final String modelName = + "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize) + LOGGER.warn( + name + " (model name starts with number) cannot be used as model name. Renamed to " + + modelName); + return modelName; + } + + return camelizedName; + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + if (serializeBigDecimalAsString) { + if (property.baseType.equals("BigDecimal")) { + // we serialize BigDecimal as `string` to avoid precision loss + property.vendorExtensions + .put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); + + // this requires some more imports to be added for this model... + model.imports.add("ToStringSerializer"); + model.imports.add("JsonSerialize"); + } + } + + if (!fullJavaUtil) { + if ("array".equals(property.containerType)) { + model.imports.add("ArrayList"); + } else if ("map".equals(property.containerType)) { + model.imports.add("HashMap"); + } + } + + if (!BooleanUtils.toBoolean(model.isEnum)) { + // needed by all pojos, but not enums + model.imports.add("ApiModelProperty"); + model.imports.add("ApiModel"); + } + + //super.postProcessModelProperty(model, property); + + if ("null".equals(property.example)) { + property.example = null; + } + + //Add imports for Jackson + if (!Boolean.TRUE.equals(model.isEnum)) { + model.imports.add("JsonProperty"); + + if (Boolean.TRUE.equals(model.hasEnums)) { + model.imports.add("JsonValue"); + } + } else { // enum class + //Needed imports for Jackson's JsonCreator + if (this.additionalProperties.containsKey("jackson")) { + model.imports.add("JsonCreator"); + } + } + } + + @Override + public Map postProcessModelsEnum(Map objs) { + objs = super.postProcessModelsEnum(objs); + + //Add imports for Jackson + List> imports = (List>) objs.get("imports"); + List models = (List) objs.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + // for enum model + if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { + cm.imports.add(this.importMapping.get("JsonValue")); + Map item = new HashMap(); + item.put("import", this.importMapping.get("JsonValue")); + imports.add(item); + } + } + + return objs; + } + + @Override + public CodegenModel fromModel(String name, Model model, Map allDefinitions) { + CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); + if (codegenModel.description != null) { + codegenModel.imports.add("ApiModel"); + } + if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { + codegenModel.imports.add("JsonSubTypes"); + codegenModel.imports.add("JsonTypeInfo"); + } + if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { + final Model parentModel = allDefinitions.get(codegenModel.parentSchema); + final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); + codegenModel = PkmstServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); + } + return codegenModel; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + return objs; + } + + @Override + public Map postProcessModels(Map objs) { + // recursively add import for mapping one type to multiple imports + List> recursiveImports = (List>) objs.get("imports"); + if (recursiveImports == null) { + return objs; + } + + ListIterator> listIterator = recursiveImports.listIterator(); + while (listIterator.hasNext()) { + String _import = listIterator.next().get("import"); + // if the import package happens to be found in the importMapping (key) + // add the corresponding import package to the list + if (importMapping.containsKey(_import)) { + Map newImportMap = new HashMap(); + newImportMap.put("import", importMapping.get(_import)); + listIterator.add(newImportMap); + } + } + + return postProcessModelsEnum(objs); + } + + @Override + public void preprocessSwagger(Swagger swagger) { + super.preprocessSwagger(swagger); + if (swagger == null || swagger.getPaths() == null) { + return; + } + if(swagger.getTags()!=null){ + System.out.println("Tags are::"+swagger.getTags()); + List resourcePaths = new ArrayList(); + for (Tag tag : swagger.getTags()) { + ResourcePath resourcePath = new ResourcePath(); + resourcePath.setPath(tag.getName()); + resourcePaths.add(resourcePath); + } + this.additionalProperties.put("resourcePaths", resourcePaths); + } + //get vendor extensions + + Map vendorExt = swagger.getInfo().getVendorExtensions(); + if(vendorExt !=null && !vendorExt.toString().equals("")){ + if(vendorExt.containsKey("x-codegen")){ + + Map uris = (Map) vendorExt.get("x-codegen"); + if(uris.containsKey("eurekaUri")){ + String eurekaUri = uris.get("eurekaUri"); + additionalProperties.put(EUREKA_URI,eurekaUri); + } + if(uris.containsKey("zipkinUri")){ + String zipkinUri = uris.get("zipkinUri"); + additionalProperties.put(ZIPKIN_URI, zipkinUri); + } + if(uris.containsKey("springBootAdminUri")){ + String springBootAdminUri = uris.get("springBootAdminUri"); + additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); + } + if(uris.containsKey("pkmstInterceptor")){ + String pkmstInterceptor = uris.get("pkmstInterceptor"); + additionalProperties.put("pkmstInterceptor", pkmstInterceptor); + } + } + } + + + + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() == null) { + continue; + } + for (Operation operation : path.getOperations()) { + boolean hasFormParameters = false; + for (Parameter parameter : operation.getParameters()) { + if (parameter instanceof FormParameter) { + hasFormParameters = true; + } + } + //only add content-Type if its no a GET-Method + if (path.getGet() != null || !operation.equals(path.getGet())) { + String defaultContentType = + hasFormParameters ? "application/x-www-form-urlencoded" : "application/json"; + String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() + ? defaultContentType : operation.getConsumes().get(0); + operation.setVendorExtension("x-contentType", contentType); + } + String accepts = getAccept(operation); + operation.setVendorExtension("x-accepts", accepts); + } + } + + if ("/".equals(swagger.getBasePath())) { + swagger.setBasePath(""); + } + + if (!additionalProperties.containsKey(TITLE)) { + // From the title, compute a reasonable name for the package and the API + String title = swagger.getInfo().getTitle(); + + // Drop any API suffix + if (title != null) { + title = title.trim().replace(" ", "-"); + if (title.toUpperCase().endsWith("API")) { + title = title.substring(0, title.length() - 3); + } + + this.title = camelize(sanitizeName(title), true); + } + additionalProperties.put(TITLE, this.title); + } + + String host = swagger.getHost(); + String port = "8008"; + if (host != null) { + String[] parts = host.split(":"); + if (parts.length > 1) { + port = parts[1]; + } + } + + this.additionalProperties.put("serverPort", port); + if (swagger.getPaths() != null) { + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() != null) { + for (Operation operation : path.getOperations()) { + if (operation.getTags() != null) { + List> tags = new ArrayList>(); + for (String tag : operation.getTags()) { + Map value = new HashMap(); + value.put("tag", tag); + value.put("hasMore", "true"); + tags.add(value); + } + if (tags.size() > 0) { + tags.get(tags.size() - 1).remove("hasMore"); + } + if (operation.getTags().size() > 0) { + String tag = operation.getTags().get(0); + operation.setTags(Arrays.asList(tag)); + } + operation.setVendorExtension("x-tags", tags); + } + } + } + } + } + } + + @Override + public void addOperationToGroup(String tag, String resourcePath, Operation operation, + CodegenOperation co, Map> operations) { + String basePath = resourcePath; + if (basePath.startsWith("/")) { + basePath = basePath.substring(1); + } + int pos = basePath.indexOf("/"); + if (pos > 0) { + basePath = basePath.substring(0, pos); + } + + if (basePath.equals("")) { + basePath = "default"; + } else { + co.subresourceOperation = !co.path.isEmpty(); + } + List opList = operations.get(basePath); + if (opList == null) { + opList = new ArrayList(); + operations.put(basePath, opList); + } + opList.add(co); + co.baseName = basePath; + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultApi"; + } + name = sanitizeName(name); + return camelize(name) + "Api"; + } + + @Override + public void setParameterExampleValue(CodegenParameter p) { + String type = p.baseType; + if (type == null) { + type = p.dataType; + } + + if ("File".equals(type)) { + String example; + + if (p.defaultValue == null) { + example = p.example; + } else { + example = p.defaultValue; + } + + if (example == null) { + example = "/path/to/file"; + } + example = + "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText( + example) + "\"))"; + p.example = example; + } else { + super.setParameterExampleValue(p); + } + } + + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; + } + + @Override + public String apiFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String apiTestFileFolder() { + return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String modelFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); + } + + @Override + public String apiDocFileFolder() { + return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); + } + + @Override + public String modelDocFileFolder() { + return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName( + name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + + if (name.toLowerCase().matches("^_*class$")) { + return "propertyClass"; + } + + if ("_".equals(name)) { + name = "_u"; + } + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + if (startsWithTwoUppercaseLetters(name)) { + name = name.substring(0, 2).toLowerCase() + name.substring(2); + } + + // camelize (lower first character) the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved word or word starting with number, append _ + if (isReservedWord(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public String toParamName(String name) { + // to avoid conflicts with 'callback' parameter for async call + if ("callback".equals(name)) { + return "paramCallback"; + } + + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + if (inner == null) { + LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning null + return null; + } + return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + if (inner == null) { + LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning null + return null; + } + return getSwaggerType(p) + ""; + } + return super.getTypeDeclaration(p); + } + + @Override + public String toDefaultValue(Property p) { + if (p instanceof ArrayProperty) { + final ArrayProperty ap = (ArrayProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.ArrayList<%s>()"; + } else { + pattern = "new ArrayList<%s>()"; + } + if (ap.getItems() == null) { + return null; + } + + return String.format(pattern, getTypeDeclaration(ap.getItems())); + } else if (p instanceof MapProperty) { + final MapProperty ap = (MapProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.HashMap<%s>()"; + } else { + pattern = "new HashMap<%s>()"; + } + if (ap.getAdditionalProperties() == null) { + return null; + } + + return String.format(pattern, + String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); + } else if (p instanceof IntegerProperty) { + IntegerProperty dp = (IntegerProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + return "null"; + } else if (p instanceof LongProperty) { + LongProperty dp = (LongProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "l"; + } + return "null"; + } else if (p instanceof DoubleProperty) { + DoubleProperty dp = (DoubleProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "d"; + } + return "null"; + } else if (p instanceof FloatProperty) { + FloatProperty dp = (FloatProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "f"; + } + return "null"; + } else if (p instanceof BooleanProperty) { + BooleanProperty bp = (BooleanProperty) p; + if (bp.getDefault() != null) { + return bp.getDefault().toString(); + } + return "null"; + } else if (p instanceof StringProperty) { + StringProperty sp = (StringProperty) p; + if (sp.getDefault() != null) { + String _default = sp.getDefault(); + if (sp.getEnum() == null) { + return "\"" + escapeText(_default) + "\""; + } else { + // convert to enum var name later in postProcessModels + return _default; + } + } + return "null"; + } + return super.toDefaultValue(p); + } + + @Override + public String toExampleValue(Property p) { + if (p.getExample() != null) { + return escapeText(p.getExample().toString()); + } else { + return super.toExampleValue(p); + } + } + + @Override + public String toOperationId(String operationId) { + // throw exception if method name is empty + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method/operation name (operationId) not allowed"); + } + + operationId = camelize(sanitizeName(operationId), true); + + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + String newOperationId = camelize("call_" + operationId, true); + LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + + newOperationId); + return newOperationId; + } + + return operationId; + } + + @Override + protected boolean needToImport(String type) { + return super.needToImport(type) && type.indexOf(".") < 0; + } + + @Override + public String toEnumName(CodegenProperty property) { + return sanitizeName(camelize(property.name)) + "Enum"; + } + + @Override + public String toEnumVarName(String value, String datatype) { + if (value.length() == 0) { + return "EMPTY"; + } + + // for symbol, e.g. $, # + if (getSymbolName(value) != null) { + return getSymbolName(value).toUpperCase(); + } + + // number + if ("Integer".equals(datatype) || "Long".equals(datatype) || + "Float".equals(datatype) || "Double".equals(datatype)) { + String varName = "NUMBER_" + value; + varName = varName.replace("-", "MINUS_"); + varName = varName.replace("\\+", "PLUS_"); + varName = varName.replace("\\.", "_DOT_"); + return varName; + } + + // string + String var = value.replace("\\W+", "_").toUpperCase(); + if (var.matches("\\d.*")) { + return "_" + var; + } else { + return var; + } + } + + @Override + public String toEnumValue(String value, String datatype) { + if ("Integer".equals(datatype) || "Long".equals(datatype) || + "Double".equals(datatype)) { + return value; + } else if ("Float".equals(datatype)) { + // add f to number, e.g. 3.14 => 3.14f + return value + "f"; + } else { + return "\"" + escapeText(value) + "\""; + } + } + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, + Map definitions, Swagger swagger) { + CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); + op.path = sanitizePath(op.path); + return op; + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + public boolean convertPropertyToBoolean(String propertyKey) { + boolean booleanValue = false; + if (additionalProperties.containsKey(propertyKey)) { + booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); + } + + return booleanValue; + } + + public String toRegularExpression(String pattern) { + return escapeText(pattern); + } + + @Override + public String sanitizeTag(String tag) { + return camelize(sanitizeName(tag)); + } + + public String toBooleanGetter(String name) { + return "is" + getterAndSetterCapitalize(name); + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getArtifactVersion() { + return artifactVersion; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + + public String getProjectFolder() { + return projectFolder; + } + + public void setProjectFolder(String projectFolder) { + this.projectFolder = projectFolder; + } + + public String getEurekaUri() { + return eurekaUri; + } + + public void setEurekaUri(String eurekaUri) { + this.eurekaUri = eurekaUri; + } + + public String getZipkinUri() { + return zipkinUri; + } + + public void setZipkinUri(String zipkinUri) { + this.zipkinUri = zipkinUri; + } + + public String getSpringBootAdminUri() { + return springBootAdminUri; + } + + public void setSpringBootAdminUri(String springBootAdminUri) { + this.springBootAdminUri = springBootAdminUri; + } + public String getProjectTestFolder() { + return projectTestFolder; + } + + public void setProjectTestFolder(String projectTestFolder) { + this.projectTestFolder = projectTestFolder; + } + + public String getSourceFolder() { + return sourceFolder; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } + + public String getTestFolder() { + return testFolder; + } + + public void setTestFolder(String testFolder) { + this.testFolder = testFolder; + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getConfigPackage() { + return configPackage; + } + + public void setConfigPackage(String configPackage) { + this.configPackage = configPackage; + } + + public boolean isImplicitHeaders() { + return implicitHeaders; + } + + public void setImplicitHeaders(boolean implicitHeaders) { + this.implicitHeaders = implicitHeaders; + } + + public boolean isSerializeBigDecimalAsString() { + return serializeBigDecimalAsString; + } + + public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { + this.serializeBigDecimalAsString = serializeBigDecimalAsString; + } + + public boolean isFullJavaUtil() { + return fullJavaUtil; + } + + public void setFullJavaUtil(boolean fullJavaUtil) { + this.fullJavaUtil = fullJavaUtil; + } + + public Boolean getSerializableModel() { + return serializableModel; + } + + public void setSerializableModel(Boolean serializableModel) { + this.serializableModel = serializableModel; + } + + public String getInvokerPackage() { + return invokerPackage; + } + + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public boolean isWithXml() { + return withXml; + } + + public void setWithXml(boolean withXml) { + this.withXml = withXml; + } + + private boolean startsWithTwoUppercaseLetters(String name) { + boolean startsWithTwoUppercaseLetters = false; + if (name.length() > 1) { + startsWithTwoUppercaseLetters = name.substring(0, 2) + .equals(name.substring(0, 2).toUpperCase()); + } + return startsWithTwoUppercaseLetters; + } + + private String sanitizePath(String p) { + //prefer replace a ", instead of a fuLL URL encode for readability + return p.replace("\"", "%22"); + } + + private interface DataTypeAssigner { + + void setReturnType(String returnType); + + void setReturnContainer(String returnContainer); + } + + private class ResourcePath { + + private String path; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + @Override + public String toString() { + return this.path; + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 804ad41368f..9ac4e8973d9 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -82,3 +82,4 @@ io.swagger.codegen.languages.TypeScriptJqueryClientCodegen io.swagger.codegen.languages.TypeScriptNodeClientCodegen io.swagger.codegen.languages.UndertowCodegen io.swagger.codegen.languages.ZendExpressivePathHandlerServerCodegen +io.swagger.codegen.languages.PkmstServerCodegen diff --git a/modules/swagger-codegen/src/main/resources/pkmst/RFC3339DateFormat.mustache b/modules/swagger-codegen/src/main/resources/pkmst/RFC3339DateFormat.mustache new file mode 100644 index 00000000000..afe24ed9aba --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/RFC3339DateFormat.mustache @@ -0,0 +1,20 @@ +package {{basePackage}}; + +import com.fasterxml.jackson.databind.util.ISO8601DateFormat; +import com.fasterxml.jackson.databind.util.ISO8601Utils; + +import java.text.FieldPosition; +import java.util.Date; + + +public class RFC3339DateFormat extends ISO8601DateFormat { + + // Same as ISO8601DateFormat but serializing milliseconds. + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + String value = ISO8601Utils.format(date, true); + toAppendTo.append(value); + return toAppendTo; + } + +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/SpringBootApplication.mustache b/modules/swagger-codegen/src/main/resources/pkmst/SpringBootApplication.mustache new file mode 100644 index 00000000000..30ef294c8b2 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/SpringBootApplication.mustache @@ -0,0 +1,36 @@ +package {{basePackage}}; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +{{#eurekaUri}} +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +{{/eurekaUri}} +import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * starts the spring boot application + * @author pkmst + * + */ + +@SpringBootApplication +@EnableSwagger2 +{{#eurekaUri}} +@EnableEurekaClient +{{/eurekaUri}} +@EnableCircuitBreaker +@EnableHystrixDashboard +public class {{serviceName}}Application { + + private static final Logger LOGGER = LoggerFactory.getLogger({{serviceName}}Application.class); + + public static void main(String[] args) { + LOGGER.debug("Running spring boot application"); + SpringApplication.run({{serviceName}}Application.class, args); + } +} + diff --git a/modules/swagger-codegen/src/main/resources/pkmst/api.mustache b/modules/swagger-codegen/src/main/resources/pkmst/api.mustache new file mode 100644 index 00000000000..27a199fba13 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/api.mustache @@ -0,0 +1,87 @@ +/** + * NOTE: This class is auto generated by the swagger code generator program ({{{generatorVersion}}}). + * https://github.com/swagger-api/swagger-codegen + * Do not edit the class manually. + */ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import io.swagger.annotations.*; +{{#jdk8}} +import org.springframework.http.HttpStatus; +{{/jdk8}} +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +{{^useSpringCloudClient}} +import java.io.IOException; +{{/useSpringCloudClient}} + +import java.util.List; +{{#useOptional}} +import java.util.Optional; +{{/useOptional}} +{{#async}} +import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}}; +{{/async}} +{{#useBeanValidation}} +import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +/** + * Provides the info about api methods + * @author pkmst + * + */ +{{>generatedAnnotation}} +@Api(value = "{{{baseName}}}", description = "the {{{baseName}}} API") +{{#operations}} +public interface {{classname}} { +{{#operation}} + + @ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}", response = {{{returnType}}}.class{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = { + {{#authMethods}}@Authorization(value = "{{name}}"{{#isOAuth}}, scopes = { + {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{#hasMore}}, + {{/hasMore}}{{/scopes}} + }{{/isOAuth}}){{#hasMore}}, + {{/hasMore}}{{/authMethods}} + }{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}",{{/vendorExtensions.x-tags}} }) + @ApiResponses(value = { {{#responses}} + @ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{baseType}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{containerType}}}"{{/containerType}}){{#hasMore}},{{/hasMore}}{{/responses}} }) + {{#implicitHeaders}} + @ApiImplicitParams({ + {{#headerParams}}{{>implicitHeader}}{{/headerParams}} + }) + {{/implicitHeaders}} + @RequestMapping(value = "{{{path}}}",{{#singleContentTypes}} + produces = "{{{vendorExtensions.x-accepts}}}", + consumes = "{{{vendorExtensions.x-contentType}}}",{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}} + produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}} + consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}} + method = RequestMethod.{{httpMethod}}) +{{#useSpringCloudClient}} + {{#jdk8}}default {{/jdk8}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/allParams}}){{^jdk8}};{{/jdk8}}{{#jdk8}} { + // do some magic! + return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<{{>returnTypes}}>(HttpStatus.NOT_IMPLEMENTED){{#async}}){{/async}}; + }{{/jdk8}} + +{{/useSpringCloudClient}} +{{^useSpringCloudClient}} + {{#jdk8}}default {{/jdk8}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}},{{/allParams}} @RequestHeader(value = "Accept", required = false) String accept) throws Exception{{^jdk8}};{{/jdk8}}{{#jdk8}} { + // do some magic! + return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK){{#async}}){{/async}}; + }{{/jdk8}} + +{{/useSpringCloudClient}} +{{/operation}} +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/apiController.mustache b/modules/swagger-codegen/src/main/resources/pkmst/apiController.mustache new file mode 100644 index 00000000000..602df07de08 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/apiController.mustache @@ -0,0 +1,115 @@ +package {{package}}; + +{{^jdk8-no-delegate}} +{{#imports}}import {{import}}; +{{/imports}} + +import io.swagger.annotations.*; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +{{/jdk8-no-delegate}} +import org.springframework.stereotype.Controller; +{{^jdk8-no-delegate}} +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +{{#useOptional}} +import java.util.Optional; +{{/useOptional}} +{{#async}} +import java.util.concurrent.Callable; +{{/async}} +{{/jdk8-no-delegate}} +{{^useSpringCloudClient}} +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +{{/useSpringCloudClient}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +/** + * Api implemention + * @author pkmst + * + */ +{{>generatedAnnotation}} +@Controller +{{#operations}} +public class {{classname}}Controller implements {{classname}} { + private final ObjectMapper objectMapper; +@Autowired + public {{classname}}Controller(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + +{{#isDelegate}} + private final {{classname}}Delegate delegate; + + @org.springframework.beans.factory.annotation.Autowired + public {{classname}}Controller({{classname}}Delegate delegate) { + this.delegate = delegate; + } + +{{/isDelegate}} +{{^jdk8-no-delegate}} +{{#operation}} + public {{#async}}Callable<{{/async}}ResponseEntity<{{>returnTypes}}>{{#async}}>{{/async}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}, + {{/allParams}}@RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! +{{#useSpringCloudClient}} + {{^isDelegate}} + {{^async}} + return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK); + {{/async}} + {{#async}} + return new CallablereturnTypes}}>>() { + @Override + public ResponseEntity<{{>returnTypes}}> call() throws Exception { + return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK); + } + }; + {{/async}} + {{/isDelegate}} + {{#isDelegate}} + return delegate.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/isDelegate}} +{{/useSpringCloudClient}} +{{^useSpringCloudClient}} + {{^isDelegate}} + {{^async}} + {{#examples}} + + if (accept != null && accept.contains("{{{contentType}}}")) { + return new ResponseEntity<{{>returnTypes}}>(objectMapper.readValue("{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{example}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{>exampleReturnTypes}}.class), HttpStatus.OK); + } + + {{/examples}} + return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK); + {{/async}} + {{#async}} + return new CallablereturnTypes}}>>() { + @Override + public ResponseEntity<{{>returnTypes}}> call() throws Exception { + return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK); + } + }; + {{/async}} + {{/isDelegate}} + {{#isDelegate}} + return delegate.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/isDelegate}} +{{/useSpringCloudClient}} + } + +{{/operation}} +{{/jdk8-no-delegate}} +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/apiException.mustache b/modules/swagger-codegen/src/main/resources/pkmst/apiException.mustache new file mode 100644 index 00000000000..f6161147700 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/apiException.mustache @@ -0,0 +1,10 @@ +package {{apiPackage}}; + +{{>generatedAnnotation}} +public class ApiException extends Exception{ + private int code; + public ApiException (int code, String msg) { + super(msg); + this.code = code; + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/apiOriginFilter.mustache b/modules/swagger-codegen/src/main/resources/pkmst/apiOriginFilter.mustache new file mode 100644 index 00000000000..5cf72a7dc42 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/apiOriginFilter.mustache @@ -0,0 +1,27 @@ +package {{apiPackage}}; + +import java.io.IOException; + +import javax.servlet.*; +import javax.servlet.http.HttpServletResponse; + +{{>generatedAnnotation}} +public class ApiOriginFilter implements javax.servlet.Filter { + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + HttpServletResponse res = (HttpServletResponse) response; + res.addHeader("Access-Control-Allow-Origin", "*"); + res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); + res.addHeader("Access-Control-Allow-Headers", "Content-Type"); + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/apiResponseMessage.mustache b/modules/swagger-codegen/src/main/resources/pkmst/apiResponseMessage.mustache new file mode 100644 index 00000000000..17b155f3b69 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/apiResponseMessage.mustache @@ -0,0 +1,69 @@ +package {{apiPackage}}; + +import javax.xml.bind.annotation.XmlTransient; + +{{>generatedAnnotation}} +@javax.xml.bind.annotation.XmlRootElement +public class ApiResponseMessage { + public static final int ERROR = 1; + public static final int WARNING = 2; + public static final int INFO = 3; + public static final int OK = 4; + public static final int TOO_BUSY = 5; + + int code; + String type; + String message; + + public ApiResponseMessage(){} + + public ApiResponseMessage(int code, String message){ + this.code = code; + switch(code){ + case ERROR: + setType("error"); + break; + case WARNING: + setType("warning"); + break; + case INFO: + setType("info"); + break; + case OK: + setType("ok"); + break; + case TOO_BUSY: + setType("too busy"); + break; + default: + setType("unknown"); + break; + } + this.message = message; + } + + @XmlTransient + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/api_doc.mustache b/modules/swagger-codegen/src/main/resources/pkmst/api_doc.mustache new file mode 100644 index 00000000000..bbb5b66f840 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/api_doc.mustache @@ -0,0 +1,82 @@ +# {{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +# **{{operationId}}** +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example +```java +// Import classes:{{#hasAuthMethods}} +//import {{{invokerPackage}}}.ApiClient;{{/hasAuthMethods}} +//import {{{invokerPackage}}}.ApiException;{{#hasAuthMethods}} +//import {{{invokerPackage}}}.Configuration; +//import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +//import {{{package}}}.{{{classname}}}; + +{{#hasAuthMethods}} +ApiClient defaultClient = Configuration.getDefaultApiClient(); +{{#authMethods}}{{#isBasic}} +// Configure HTTP basic authorization: {{{name}}} +HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setUsername("YOUR USERNAME"); +{{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} +// Configure API key authorization: {{{name}}} +ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setApiKey("YOUR API KEY"); +// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) +//{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} +// Configure OAuth2 access token for authorization: {{{name}}} +OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} +{{/authMethods}} +{{/hasAuthMethods}} + +{{{classname}}} apiInstance = new {{{classname}}}(); +{{#allParams}} +{{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} +{{/allParams}} +try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + System.out.println(result);{{/returnType}} +} catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + e.printStackTrace(); +} +``` + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{/operation}} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/api_test.mustache b/modules/swagger-codegen/src/main/resources/pkmst/api_test.mustache new file mode 100644 index 00000000000..615a0b9b71f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/api_test.mustache @@ -0,0 +1,57 @@ +{{>licenseInfo}} + +package {{package}}; + +import com.fasterxml.jackson.databind.ObjectMapper; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final {{classname}} api = new {{classname}}Controller(objectMapper); + + private final String accept = "application/json"; + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws Exception + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws Exception { + {{#allParams}} + {{^isFile}} + {{{dataType}}} {{paramName}} = null; + {{/isFile}} + {{#isFile}} + MultipartFile {{paramName}} = null; + {{/isFile}} + {{/allParams}} + ResponseEntity<{{>returnTypes}}> response = api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}} {{#allParams}}{{^hasMore}},{{/hasMore}}{{/allParams}} accept); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/bodyParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/bodyParams.mustache new file mode 100644 index 00000000000..7fef9ad2b6f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{/isContainer}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestBody {{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/config/appconfig.mustache b/modules/swagger-codegen/src/main/resources/pkmst/config/appconfig.mustache new file mode 100644 index 00000000000..67d99d563e8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/config/appconfig.mustache @@ -0,0 +1,101 @@ +package {{basePackage}}.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +{{#pkmstInterceptor}} +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import com.prokarma.pkmst.interceptor.AuditInterceptor; +import com.prokarma.pkmst.interceptor.BodyInterceptor; +//import com.prokarma.pkmst.interceptor.CorrelationInterceptor; +import com.prokarma.pkmst.interceptor.RateLimitInterceptor; +import com.prokarma.pkmst.interceptor.TraceabilityInterceptor; +{{/pkmstInterceptor}} +/** + * Registers the interceptors which are configurable via yaml + * @author pkmst + * + */ +@Configuration +public class AppConfig extends WebMvcConfigurerAdapter { + {{#pkmstInterceptor}} + @Value("${interceptor.enable.traceability:false}") + boolean traceabilityEnable; + @Bean + public HandlerInterceptor traceabilityInterceptor() { + return new TraceabilityInterceptor(); + } + @Value("${interceptor.enable.correlation:false}") + boolean correlationEnable; + /*@Bean + public HandlerInterceptor correlationInterceptor() { + return new CorrelationInterceptor(); + }*/ + @Value("${interceptor.enable.rateLimit:false}") + boolean rateLimitEnable; + @Bean + public HandlerInterceptor rateLimitInterceptor() { + return new RateLimitInterceptor(); + } + @Value("${interceptor.enable.audit:false}") + boolean auditEnable; + @Bean + public HandlerInterceptor auditInterceptor() { + return new AuditInterceptor(); + } + @Value("${interceptor.enable.body:false}") + boolean bodyEnable; + @Bean + public HandlerInterceptor bodyInterceptor() { + return new BodyInterceptor(); + } + + + @Override + public void addInterceptors(InterceptorRegistry registry) { + + if (traceabilityEnable) { + registry.addInterceptor(traceabilityInterceptor()); + } + if (correlationEnable) { + // registry.addInterceptor(correlationInterceptor); + } + if (rateLimitEnable) { + registry.addInterceptor(rateLimitInterceptor()); + } + if (auditEnable) { + registry.addInterceptor(auditInterceptor()); + } + if (bodyEnable) { + registry.addInterceptor(bodyInterceptor()); + } + + + + } + + {{/pkmstInterceptor}} + /** + * enabling cors support at global level which can be applied at various + * level also as below registry.addMapping("/api/**") + * .allowedOrigins("http://domain2.com") .allowedMethods("PUT", "DELETE") + * .allowedHeaders("header1", "header2", "header3") + * .exposedHeaders("header1", "header2") + * .allowCredentials(false).maxAge(3600); + * + * @return + */ + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurerAdapter() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**"); + } + }; + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/config/pkmstproperties.mustache b/modules/swagger-codegen/src/main/resources/pkmst/config/pkmstproperties.mustache new file mode 100644 index 00000000000..86554ed8cc8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/config/pkmstproperties.mustache @@ -0,0 +1,113 @@ +package {{basePackage}}.config.swagger; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +/** + * Provides the swagger API info + * @author pkmst + * + */ +@Configuration +@ConfigurationProperties(prefix = "pkmst", ignoreUnknownFields = false) +public class PkmstProperties { + + private final Swagger swagger = new Swagger(); + + + public Swagger getSwagger() { + return swagger; + } + + + public static class Swagger { + + private String title = "Pkmst API"; + + private String description = "Pkmst API documentation"; + + private String version = "0.0.1"; + + private String termsOfServiceUrl; + + private String contactName; + + private String contactUrl; + + private String contactEmail; + + private String license; + + private String licenseUrl; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getTermsOfServiceUrl() { + return termsOfServiceUrl; + } + + public void setTermsOfServiceUrl(String termsOfServiceUrl) { + this.termsOfServiceUrl = termsOfServiceUrl; + } + + public String getContactName() { + return contactName; + } + + public void setContactName(String contactName) { + this.contactName = contactName; + } + + public String getContactUrl() { + return contactUrl; + } + + public void setContactUrl(String contactUrl) { + this.contactUrl = contactUrl; + } + + public String getContactEmail() { + return contactEmail; + } + + public void setContactEmail(String contactEmail) { + this.contactEmail = contactEmail; + } + + public String getLicense() { + return license; + } + + public void setLicense(String license) { + this.license = license; + } + + public String getLicenseUrl() { + return licenseUrl; + } + + public void setLicenseUrl(String licenseUrl) { + this.licenseUrl = licenseUrl; + } + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/config/swaggerDocumentationConfig.mustache b/modules/swagger-codegen/src/main/resources/pkmst/config/swaggerDocumentationConfig.mustache new file mode 100644 index 00000000000..08c74b4b824 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/config/swaggerDocumentationConfig.mustache @@ -0,0 +1,61 @@ +package {{basePackage}}.config.swagger; + +import java.util.Date; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StopWatch; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +//import static springfox.documentation.builders.PathSelectors.regex; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; +/** + * Enable swagger ui for application + * @author pkmst + * + */ +@EnableSwagger2 +@Configuration +public class SwaggerDocumentationConfig { + + public static final String DEFAULT_INCLUDE_PATTERN = "/pkmst/.*"; + @Bean + public Docket swaggerSpringfoxDocket(PkmstProperties pkmstProperties) { + StopWatch watch = new StopWatch(); + watch.start(); + Contact contact = new Contact( + pkmstProperties.getSwagger().getContactName(), + pkmstProperties.getSwagger().getContactUrl(), + pkmstProperties.getSwagger().getContactEmail()); + + ApiInfo apiInfo = new ApiInfo( + pkmstProperties.getSwagger().getTitle(), + pkmstProperties.getSwagger().getDescription(), + pkmstProperties.getSwagger().getVersion(), + pkmstProperties.getSwagger().getTermsOfServiceUrl(), + contact, + pkmstProperties.getSwagger().getLicense(), + pkmstProperties.getSwagger().getLicenseUrl()); + + Docket docket = new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo) + .forCodeGeneration(true) + .genericModelSubstitutes(ResponseEntity.class) + .ignoredParameterTypes(java.sql.Date.class) + .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(java.time.ZonedDateTime.class, Date.class) + .directModelSubstitute(java.time.LocalDateTime.class, Date.class) + .select() + .apis(RequestHandlerSelectors.basePackage("com.prokarma.pkmst")) + // .paths(regex(DEFAULT_INCLUDE_PATTERN)) + .paths(PathSelectors.any()) + .build(); + watch.stop(); + return docket; + } + +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumber.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumber.mustache new file mode 100644 index 00000000000..a22095793d4 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumber.mustache @@ -0,0 +1,33 @@ +#Feature: List of scenarios. +#Scenario: Business rule through list of steps with arguments. +#Given: Some precondition step +#When: Some key actions +#Then: To observe outcomes or validation +#And,But: To enumerate more Given,When,Then steps +#Scenario Outline: List of steps for data-driven as an Examples and + +#Sample Feature Definition Template +@tag +Feature: Title of your feature + I want to use this template for my feature file + +@tag1 +Scenario: Title of your scenario +Given I want to write a step with precondition + And some other precondition +When I complete action + And some other action + And yet another action +Then I validate the outcomes + And check more outcomes + +@tag2 +Scenario Outline: Title of your scenario outline +Given I want to write a step with +When I check for the in step +Then I verify the in step + +Examples: + | name |value | status | + | name1 | 5 | success| + | name2 | 7 | Fail | \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberSteps.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberSteps.mustache new file mode 100644 index 00000000000..d2c9398f7cd --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberSteps.mustache @@ -0,0 +1,76 @@ +package {{basePackage}}.cucumber; +import cucumber.api.java.After; +import cucumber.api.java.Before; +import cucumber.api.java.en.Given; +import cucumber.api.java.en.Then; +import cucumber.api.java.en.When; +import cucumber.api.PendingException; + +public class {{serviceName}}Steps { + +@Given("^I want to write a step with precondition$") +public void i_want_to_write_a_step_with_precondition() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Given("^some other precondition$") +public void some_other_precondition() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^I complete action$") +public void i_complete_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^some other action$") +public void some_other_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^yet another action$") +public void yet_another_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I validate the outcomes$") +public void i_validate_the_outcomes() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^check more outcomes$") +public void check_more_outcomes() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Given("^I want to write a step with name(\\d+)$") +public void i_want_to_write_a_step_with_name(int arg1) throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^I check for the (\\d+) in step$") +public void i_check_for_the_in_step(int arg1) throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I verify the success in step$") +public void i_verify_the_success_in_step() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I verify the Fail in step$") +public void i_verify_the_Fail_in_step() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberTest.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberTest.mustache new file mode 100644 index 00000000000..684121ae59b --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/cucumberTest.mustache @@ -0,0 +1,15 @@ +package {{basePackage}}.cucumber; + +import org.junit.runner.RunWith; +import org.springframework.test.context.ActiveProfiles; +import cucumber.api.CucumberOptions; +import cucumber.api.junit.Cucumber; + +@RunWith(Cucumber.class) +@ActiveProfiles("test") +@CucumberOptions(format = { "pretty", "html:target/cucumber-html-report", +{{#resourcePaths}} + "json:./report/{{path}}-report-json/{{path}}.json", +{{/resourcePaths}} }) +public class {{serviceName}}Test { +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/executeReport.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/executeReport.mustache new file mode 100644 index 00000000000..c60e1ca5642 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/executeReport.mustache @@ -0,0 +1,42 @@ +package {{basePackage}}.cucumber.report; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import net.masterthought.cucumber.Configuration; +import net.masterthought.cucumber.ReportBuilder; + +public class ExecuteReport { + + public static void main(String[] args) { + generateReport(); + } + + private static void generateReport() { + String buildNumber = "1"; + String projectName = "Spring-micro-sample"; + boolean runWithJenkins = false; + boolean parallelTesting = false; + + File reportOutputDirectory = null; + List jsonFiles = null; + Configuration configuration = null; + ReportBuilder reportBuilder = null; + {{#resourcePaths}} + reportOutputDirectory = new File("./report/{{path}}-report-html/"); + jsonFiles = new ArrayList(); + jsonFiles.add("./report/{{path}}-report-json/{{path}}.json"); + + configuration = new Configuration(reportOutputDirectory,projectName); + // optionally only if you need + configuration.setParallelTesting(parallelTesting); + configuration.setRunWithJenkins(runWithJenkins); + configuration.setBuildNumber(buildNumber); + + reportBuilder = new ReportBuilder(jsonFiles, configuration); + reportBuilder.generateReports(); + {{/resourcePaths}} + + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/cucumber/package.mustache b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/package.mustache new file mode 100644 index 00000000000..cfc71028133 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/cucumber/package.mustache @@ -0,0 +1,2 @@ +package {{basePackage}}.cucumber; +//Implement the feature file steps in this package. \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/docker.mustache b/modules/swagger-codegen/src/main/resources/pkmst/docker.mustache new file mode 100644 index 00000000000..a742c3dbb10 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/docker.mustache @@ -0,0 +1,3 @@ +FROM frolvlad/alpine-oraclejdk8:slim +COPY target/{{artifactId}}.jar app.jar +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/enumClass.mustache b/modules/swagger-codegen/src/main/resources/pkmst/enumClass.mustache new file mode 100644 index 00000000000..c5c3143cb94 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/enumClass.mustache @@ -0,0 +1,44 @@ + /** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} + */ + public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { + {{#gson}} + {{#allowableValues}} + {{#enumVars}} + @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}} + {{/enumVars}} + {{/allowableValues}} + {{/gson}} + {{^gson}} + {{#allowableValues}} + {{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}} + {{/enumVars}} + {{/allowableValues}} + {{/gson}} + + private {{{datatype}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{datatype}}} value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } + } diff --git a/modules/swagger-codegen/src/main/resources/pkmst/exampleReturnTypes.mustache b/modules/swagger-codegen/src/main/resources/pkmst/exampleReturnTypes.mustache new file mode 100644 index 00000000000..395e3889c20 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/exampleReturnTypes.mustache @@ -0,0 +1 @@ +{{#returnContainer}}{{#isMapContainer}}Map{{/isMapContainer}}{{#isListContainer}}List{{/isListContainer}}{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/formParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/formParams.mustache new file mode 100644 index 00000000000..8f6cb5213c4 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}@ApiParam(value = "{{{description}}}"{{#required}}, required=true{{/required}}{{#allowableValues}}, allowableValues="{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @RequestPart(value="{{baseName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}}) {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}@ApiParam(value = "file detail") {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestPart("file") MultipartFile {{baseName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/gatling/application.mustache b/modules/swagger-codegen/src/main/resources/pkmst/gatling/application.mustache new file mode 100644 index 00000000000..6a42f95f1fa --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/gatling/application.mustache @@ -0,0 +1,14 @@ +#################################### +# Akka Actor Config File # +#################################### + +akka { + scheduler { + tick-duration = 50ms + } +} + +url="http://localhost:8081" +noOfUsers=10 #Number of Users +deleteProductId=4 #Delete the Product by using productID +getProduct=2 #Get the Product \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/gatling/gatling.mustache b/modules/swagger-codegen/src/main/resources/pkmst/gatling/gatling.mustache new file mode 100644 index 00000000000..c7b4fa7f8c8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/gatling/gatling.mustache @@ -0,0 +1,157 @@ +######################### +# Gatling Configuration # +######################### + +# This file contains all the settings configurable for Gatling with their default values + +gatling { + core { + #outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp) + #runDescription = "" # The description for this simulation run, displayed in each report + #encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation + #simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated) + #mute = false # When set to true, don't ask for simulation name nor run description (currently only used by Gatling SBT plugin) + + extract { + regex { + #cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching + } + xpath { + #cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching + } + jsonPath { + #cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching + #preferJackson = false # When set to true, prefer Jackson over Boon for JSON-related operations + jackson { + #allowComments = false # Allow comments in JSON files + #allowUnquotedFieldNames = false # Allow unquoted JSON fields names + #allowSingleQuotes = false # Allow single quoted JSON field names + } + + } + css { + #cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching + } + } + + timeOut { + #simulation = 8640000 # Absolute timeout, in seconds, of a simulation + } + directory { + #data = src/test/resource/data # Folder where user's data (e.g. files used by Feeders) is located + #bodies = src/test/resource/bodies # Folder where bodies are located + #simulations = user-src/test/java/simulations # Folder where the bundle's simulations are located< + #reportsOnly = "" # If set, name of report folder to look for in order to generate its report + #binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target. + #results = results # Name of the folder where all reports folder are located + } + } + charting { + #noReports = false # When set to true, don't generate HTML reports + #maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports + #accuracy = 10 # Accuracy, in milliseconds, of the report's stats + indicators { + #lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary + #higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary + #percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and GraphiteDataWriter + } + } + http { + #elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable + #rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body Raw templates, set to 0 to disable + #fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable + #fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable + #redirectPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent redirects, set to 0 to disable + #expirePerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent 'Expire' headers, set to 0 to disable + #lastModifiedPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent 'Last-Modified' headers, set to 0 to disable + #etagPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent ETag headers, set to 0 to disable + #warmUpUrl = "http://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled) + #enableGA = true # Very light Google Analytics, please support + ssl { + trustStore { + #type = "" # Type of SSLContext's TrustManagers store + #file = "" # Location of SSLContext's TrustManagers store + #password = "" # Password for SSLContext's TrustManagers store + #algorithm = "" # Algorithm used by SSLContext's TrustManagers store + } + keyStore { + #type = "" # Type of SSLContext's KeyManagers store + #file = "" # Location of SSLContext's KeyManagers store + #password = "" # Password for SSLContext's KeyManagers store + #algorithm = "" # Algorithm used SSLContext's KeyManagers store + } + } + ahc { + #allowPoolingConnections = true # Allow pooling HTTP connections (keep-alive header automatically added) + #allowPoolingSslConnections = true # Allow pooling HTTPS connections (keep-alive header automatically added) + #compressionEnforced = false # Enforce gzip/deflate when Accept-Encoding header is not defined + #connectTimeout = 60000 # Timeout when establishing a connection + #pooledConnectionIdleTimeout = 60000 # Timeout when a connection stays unused in the pool + #readTimeout = 60000 # Timeout when a used connection stays idle + #connectionTTL = -1 # Max duration a connection can stay open (-1 means no limit) + #ioThreadMultiplier = 2 # Number of Netty worker threads per core + #maxConnectionsPerHost = -1 # Max number of connections per host (-1 means no limit) + #maxConnections = -1 # Max number of connections (-1 means no limit) + #maxRetry = 2 # Number of times that a request should be tried again + #requestTimeout = 60000 # Timeout of the requests + #useProxyProperties = false # When set to true, supports standard Proxy System properties + #webSocketTimeout = 60000 # Timeout when a used websocket connection stays idle + #useRelativeURIsWithConnectProxies = true # When set to true, use relative URIs when talking with an SSL proxy or a WebSocket proxy + #acceptAnyCertificate = true # When set to true, doesn't validate SSL certificates + #httpClientCodecMaxInitialLineLength = 4096 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK") + #httpClientCodecMaxHeaderSize = 8192 # Maximum size, in bytes, of each request's headers + #httpClientCodecMaxChunkSize = 8192 # Maximum length of the content or each chunk + #keepEncodingHeader = true # Don't drop Encoding response header after decoding + #webSocketMaxFrameSize = 10240 # Maximum frame payload size + #httpsEnabledProtocols = "" # Comma separated enabled protocols for HTTPS, if empty use the JDK defaults + #httpsEnabledCipherSuites = "" # Comma separated enabled cipher suites for HTTPS, if empty use the JDK defaults + #sslSessionCacheSize = 20000 # SSLSession cache size (set to 0 to disable) + #sslSessionTimeout = 86400 # SSLSession timeout (default is 24, like Hotspot) + } + } + data { + #writers = "console, file" # The lists of DataWriters to which Gatling write simulation data (currently supported : "console", "file", "graphite", "jdbc") + #reader = file # The DataReader used by the charting engine for reading simulation results + console { + #light = false # When set to true, displays a light version without detailed request stats + } + file { + #bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes + } + leak { + #noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening + } + jdbc { + db { + #url = "jdbc:mysql://localhost:3306/temp" # The JDBC URL used by the JDBC DataWriter + #username = "root" # The database user used by the JDBC DataWriter + #password = "123123q" # The password for the specified user + } + #bufferSize = 20 # The size for each batch of SQL inserts to send to the database + create { + #createRunRecordTable = "CREATE TABLE IF NOT EXISTS `RunRecords` ( `id` INT NOT NULL AUTO_INCREMENT , `runDate` DATETIME NULL , `simulationId` VARCHAR(45) NULL , `runDescription` VARCHAR(45) NULL , PRIMARY KEY (`id`) )" + #createRequestRecordTable = "CREATE TABLE IF NOT EXISTS `RequestRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenario` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `name` varchar(50) DEFAULT NULL, `requestStartDate` bigint DEFAULT NULL, `requestEndDate` bigint DEFAULT NULL, `responseStartDate` bigint DEFAULT NULL, `responseEndDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, `message` varchar(4500) DEFAULT NULL, `responseTime` bigint DEFAULT NULL, PRIMARY KEY (`id`) )" + #createScenarioRecordTable = "CREATE TABLE IF NOT EXISTS `ScenarioRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `event` varchar(50) DEFAULT NULL, `startDate` bigint DEFAULT NULL, `endDate` bigint DEFAULT NULL, PRIMARY KEY (`id`) )" + #createGroupRecordTable = "CREATE TABLE IF NOT EXISTS `GroupRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `entryDate` bigint DEFAULT NULL, `exitDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, PRIMARY KEY (`id`) )" + } + insert { + #insertRunRecord = "INSERT INTO RunRecords (runDate, simulationId, runDescription) VALUES (?,?,?)" + #insertRequestRecord = "INSERT INTO RequestRecords (runId, scenario, userId, name, requestStartDate, requestEndDate, responseStartDate, responseEndDate, status, message, responseTime) VALUES (?,?,?,?,?,?,?,?,?,?,?)" + #insertScenarioRecord = "INSERT INTO ScenarioRecords (runId, scenarioName, userId, event, startDate, endDate) VALUES (?,?,?,?,?,?)" + #insertGroupRecord = "INSERT INTO GroupRecords (runId, scenarioName, userId, entryDate, exitDate, status) VALUES (?,?,?,?,?,?)" + } + } + graphite { + #light = false # only send the all* stats + #host = "localhost" # The host where the Carbon server is located + #port = 2003 # The port to which the Carbon server listens to + #protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp") + #rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite + #bufferSize = 8192 # GraphiteDataWriter's internal data buffer size, in bytes + #writeInterval = 1 # GraphiteDataWriter's write interval, in seconds + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/gatling/package.mustache b/modules/swagger-codegen/src/main/resources/pkmst/gatling/package.mustache new file mode 100644 index 00000000000..e69de29bb2d diff --git a/modules/swagger-codegen/src/main/resources/pkmst/gatling/testapi.mustache b/modules/swagger-codegen/src/main/resources/pkmst/gatling/testapi.mustache new file mode 100644 index 00000000000..ef5163aa929 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/gatling/testapi.mustache @@ -0,0 +1,41 @@ +# Sample gatling test for Get Product. Please implement likewise for your API. +import scala.concurrent.duration._ + +import io.gatling.core.Predef._ +import io.gatling.http.Predef._ +import io.gatling.jdbc.Predef._ +import com.typesafe.config._ +import org.springframework.boot.SpringApplication +import org.springframework.context.ConfigurableApplicationContext + + +class get{{path}} extends Simulation { + + + val app: ConfigurableApplicationContext = SpringApplication.run(classOf[{{basePackage}}.{{serviceName}}Application]) + Runtime.getRuntime.addShutdownHook(new Thread() { + override def run(): Unit = app.stop() + }) + + val conf = ConfigFactory.load() + val baseUrl = conf.getString("url") + val noOfUsers: Int = conf.getInt("noOfUsers") + val httpProtocol = http + .baseURL(baseUrl) + .inferHtmlResources() + .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") + .acceptEncodingHeader("gzip, deflate, sdch") + .acceptLanguageHeader("en-US,en;q=0.8") + .userAgentHeader("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36") + + val headers_0 = Map( + "Cache-Control" -> "max-age=0", + "Upgrade-Insecure-Requests" -> "1") + + val scn = scenario("getProduct") + .exec(http("request_0") + .get("/{{{path}}}") + .headers(headers_0)) + + setUp(scn.inject(atOnceUsers(noOfUsers))).protocols(httpProtocol) +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/generatedAnnotation.mustache b/modules/swagger-codegen/src/main/resources/pkmst/generatedAnnotation.mustache new file mode 100644 index 00000000000..ad17a426e96 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/generatedAnnotation.mustache @@ -0,0 +1,3 @@ +{{^hideGenerationTimestamp}} +@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}") +{{/hideGenerationTimestamp}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/headerParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/headerParams.mustache new file mode 100644 index 00000000000..89645c9436a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues="{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @RequestHeader(value="{{baseName}}", required={{#required}}true{{/required}}{{^required}}false{{/required}}) {{>optionalDataType}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/integration/integrationtest.mustache b/modules/swagger-codegen/src/main/resources/pkmst/integration/integrationtest.mustache new file mode 100644 index 00000000000..45ebd423d60 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/integration/integrationtest.mustache @@ -0,0 +1,34 @@ +package {{basePackage}}.controller; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; +import {{basePackage}}.{{serviceName}}Application; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {{serviceName}}Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class {{serviceName}}IT { + + @LocalServerPort + private int port; + + TestRestTemplate restTemplate = new TestRestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + + @Test + public void testYourMethod() { + + //add your logic + } + + private String createURLWithPort(String uri) { + return "http://localhost:" + port + uri; + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/licenseInfo.mustache b/modules/swagger-codegen/src/main/resources/pkmst/licenseInfo.mustache new file mode 100644 index 00000000000..94c36dda3af --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/licenseInfo.mustache @@ -0,0 +1,11 @@ +/* + * {{{appName}}} + * {{{appDescription}}} + * + * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} + * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ diff --git a/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache b/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache new file mode 100644 index 00000000000..5e09dd6090d --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache @@ -0,0 +1,434 @@ +package {{basePackage}}.logging; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ReadListener; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.WriteListener; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.output.TeeOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +/** + * Implements javax.servlet.Filter and dump the request/response to syslog + * @author pkmst + * + */ + +@Component +public class HttpLoggingFilter implements Filter { + + private static final Logger log = LoggerFactory.getLogger(HttpLoggingFilter.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { + try { + HttpServletRequest httpServletRequest = (HttpServletRequest) request; + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + Map requestMap = this.getTypesafeRequestMap(httpServletRequest); + BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpServletRequest); + BufferedResponseWrapper bufferedResponse = new BufferedResponseWrapper(httpServletResponse); + final StringBuilder logMessage = new StringBuilder( + "REST Request - ").append("[HTTP METHOD:") + .append(httpServletRequest.getMethod()) + .append("] [PATH INFO:") + .append(httpServletRequest.getServletPath()) + .append("] [REQUEST PARAMETERS:").append(requestMap) + .append("] [REQUEST BODY:") + .append(bufferedRequest.getRequestBody()) + .append("] [REMOTE ADDRESS:") + .append(httpServletRequest.getRemoteAddr()).append("]"); + long start = System.currentTimeMillis(); + chain.doFilter(bufferedRequest, bufferedResponse); + long elapsedTime = System.currentTimeMillis() - start; + String respContent = null; + if (bufferedResponse.getContent() == null || bufferedResponse.getContent() == "") { + respContent = "No data"; + } else { + respContent = bufferedResponse.getContent(); + } + logMessage.append(" [RESPONSE:").append(respContent) + .append("] [STATUS CODE:") + .append(bufferedResponse.getStatus()) + .append("] [Response Time(ms):").append(elapsedTime) + .append("]"); + log.info(logMessage.toString()); + } catch (Throwable a) { + log.error(a.getMessage()); + a.printStackTrace(); + } + } + + private Map getTypesafeRequestMap(HttpServletRequest request) { + Map typesafeRequestMap = new HashMap(); + Enumeration requestParamNames = request.getParameterNames(); + while (requestParamNames.hasMoreElements()) { + String requestParamName = (String) requestParamNames.nextElement(); + String requestParamValue; + if (requestParamName.equalsIgnoreCase("password")) { + requestParamValue = "********"; + } else { + requestParamValue = request.getParameter(requestParamName); + } + typesafeRequestMap.put(requestParamName, requestParamValue); + } + return typesafeRequestMap; + } + + @Override + public void destroy() { + } + + private static final class BufferedRequestWrapper extends HttpServletRequestWrapper { + + private ByteArrayInputStream bais = null; + private ByteArrayOutputStream baos = null; + private BufferedServletInputStream bsis = null; + private byte[] buffer = null; + + public BufferedRequestWrapper(HttpServletRequest req) throws IOException { + super(req); + // Read InputStream and store its content in a buffer. + InputStream is = req.getInputStream(); + this.baos = new ByteArrayOutputStream(); + byte buf[] = new byte[1024]; + int read; + while ((read = is.read(buf)) > 0) { + this.baos.write(buf, 0, read); + } + this.buffer = this.baos.toByteArray(); + } + + @Override + public ServletInputStream getInputStream() { + this.bais = new ByteArrayInputStream(this.buffer); + this.bsis = new BufferedServletInputStream(this.bais); + return this.bsis; + } + + String getRequestBody() throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(this.getInputStream())); + String line = null; + StringBuilder inputBuffer = new StringBuilder(); + do { + line = reader.readLine(); + if (null != line) { + inputBuffer.append(line.trim()); + } + } while (line != null); + reader.close(); + return inputBuffer.toString().trim(); + } + + } + + private static final class BufferedServletInputStream extends ServletInputStream { + + private ByteArrayInputStream bais; + + public BufferedServletInputStream(ByteArrayInputStream bais) { + this.bais = bais; + } + + @Override + public int available() { + return this.bais.available(); + } + + @Override + public int read() { + return this.bais.read(); + } + + @Override + public int read(byte[] buf, int off, int len) { + return this.bais.read(buf, off, len); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + } + + public class TeeServletOutputStream extends ServletOutputStream { + + private final TeeOutputStream targetStream; + + public TeeServletOutputStream(OutputStream one, OutputStream two) { + targetStream = new TeeOutputStream(one, two); + } + + @Override + public void write(int arg0) throws IOException { + this.targetStream.write(arg0); + } + + public void flush() throws IOException { + super.flush(); + this.targetStream.flush(); + } + + public void close() throws IOException { + super.close(); + this.targetStream.close(); + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + + } + } + + public class BufferedResponseWrapper implements HttpServletResponse { + + HttpServletResponse original; + TeeServletOutputStream tee; + ByteArrayOutputStream bos; + + public BufferedResponseWrapper(HttpServletResponse response) { + original = response; + } + + public String getContent() { + if (bos == null) { + return null; + } else + return bos.toString(); + } + + public PrintWriter getWriter() throws IOException { + return original.getWriter(); + } + + public ServletOutputStream getOutputStream() throws IOException { + if (tee == null) { + bos = new ByteArrayOutputStream(); + tee = new TeeServletOutputStream(original.getOutputStream(),bos); + } + return tee; + + } + + @Override + public String getCharacterEncoding() { + return original.getCharacterEncoding(); + } + + @Override + public String getContentType() { + return original.getContentType(); + } + + @Override + public void setCharacterEncoding(String charset) { + original.setCharacterEncoding(charset); + } + + @Override + public void setContentLength(int len) { + original.setContentLength(len); + } + + @Override + public void setContentLengthLong(long l) { + original.setContentLengthLong(l); + } + + @Override + public void setContentType(String type) { + original.setContentType(type); + } + + @Override + public void setBufferSize(int size) { + original.setBufferSize(size); + } + + @Override + public int getBufferSize() { + return original.getBufferSize(); + } + + @Override + public void flushBuffer() throws IOException { + tee.flush(); + } + + @Override + public void resetBuffer() { + original.resetBuffer(); + } + + @Override + public boolean isCommitted() { + return original.isCommitted(); + } + + @Override + public void reset() { + original.reset(); + } + + @Override + public void setLocale(Locale loc) { + original.setLocale(loc); + } + + @Override + public Locale getLocale() { + return original.getLocale(); + } + + @Override + public void addCookie(Cookie cookie) { + original.addCookie(cookie); + } + + @Override + public boolean containsHeader(String name) { + return original.containsHeader(name); + } + + @Override + public String encodeURL(String url) { + return original.encodeURL(url); + } + + @Override + public String encodeRedirectURL(String url) { + return original.encodeRedirectURL(url); + } + + @SuppressWarnings("deprecation") + @Override + public String encodeUrl(String url) { + return original.encodeUrl(url); + } + + @SuppressWarnings("deprecation") + @Override + public String encodeRedirectUrl(String url) { + return original.encodeRedirectUrl(url); + } + + @Override + public void sendError(int sc, String msg) throws IOException { + original.sendError(sc, msg); + } + + @Override + public void sendError(int sc) throws IOException { + original.sendError(sc); + } + + @Override + public void sendRedirect(String location) throws IOException { + original.sendRedirect(location); + } + + @Override + public void setDateHeader(String name, long date) { + original.setDateHeader(name, date); + } + + @Override + public void addDateHeader(String name, long date) { + original.addDateHeader(name, date); + } + + @Override + public void setHeader(String name, String value) { + original.setHeader(name, value); + } + + @Override + public void addHeader(String name, String value) { + original.addHeader(name, value); + } + + @Override + public void setIntHeader(String name, int value) { + original.setIntHeader(name, value); + } + + @Override + public void addIntHeader(String name, int value) { + original.addIntHeader(name, value); + } + + @Override + public void setStatus(int sc) { + original.setStatus(sc); + } + + @SuppressWarnings("deprecation") + @Override + public void setStatus(int sc, String sm) { + original.setStatus(sc, sm); + } + + @Override + public String getHeader(String arg0) { + return original.getHeader(arg0); + } + + @Override + public Collection getHeaderNames() { + return original.getHeaderNames(); + } + + @Override + public Collection getHeaders(String arg0) { + return original.getHeaders(arg0); + } + + @Override + public int getStatus() { + return original.getStatus(); + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/logstash.mustache b/modules/swagger-codegen/src/main/resources/pkmst/logstash.mustache new file mode 100644 index 00000000000..491be1e7f7c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/logstash.mustache @@ -0,0 +1,35 @@ +input { + file { + path => "" + start_position => "beginning" + + } +} + + +filter { + # pattern matching logback pattern + grok { + + } + + +} + + + +} + +output { + # Print each event to stdout, useful for debugging. Should be commented out in production. + # Enabling 'rubydebug' codec on the stdout output will make logstash + # pretty-print the entire event as something similar to a JSON representation. + stdout { + codec => rubydebug + } + + # Sending properly parsed log events to elasticsearch + elasticsearch { + hosts => ["localhost:9200"] + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/manifest.mustache b/modules/swagger-codegen/src/main/resources/pkmst/manifest.mustache new file mode 100644 index 00000000000..2d27f25bace --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/manifest.mustache @@ -0,0 +1,12 @@ +applications: +- name: + memory: 1G + instances: 1 + host: + buildpack: https://github.com/cloudfoundry/java-buildpack.git + path: + services: + - + - + env: + \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/model.mustache b/modules/swagger-codegen/src/main/resources/pkmst/model.mustache new file mode 100644 index 00000000000..ef8b9e7422e --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/model.mustache @@ -0,0 +1,37 @@ +package {{package}}; + +import java.util.Objects; +{{#imports}}import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#useBeanValidation}} +import org.springframework.validation.annotation.Validated; +import javax.validation.Valid; +import javax.validation.constraints.*; +{{/useBeanValidation}} +{{#jackson}} +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +/** + * Response class to be returned by Api + * @author pkmst + * + */ +{{#models}} +{{#model}} +{{#isEnum}} +{{>enumOuterClass}} +{{/isEnum}} +{{^isEnum}} +{{>pojo}} +{{/isEnum}} +{{/model}} +{{/models}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/model_doc.mustache b/modules/swagger-codegen/src/main/resources/pkmst/model_doc.mustache new file mode 100644 index 00000000000..658df8d5322 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/model_doc.mustache @@ -0,0 +1,3 @@ +{{#models}}{{#model}} +{{#isEnum}}{{>enum_outer_doc}}{{/isEnum}}{{^isEnum}}{{>pojo_doc}}{{/isEnum}} +{{/model}}{{/models}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/notFoundException.mustache b/modules/swagger-codegen/src/main/resources/pkmst/notFoundException.mustache new file mode 100644 index 00000000000..40c25c5ea5c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/notFoundException.mustache @@ -0,0 +1,10 @@ +package {{apiPackage}}; + +{{>generatedAnnotation}} +public class NotFoundException extends ApiException { + private int code; + public NotFoundException (int code, String msg) { + super(code, msg); + this.code = code; + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/optionalDataType.mustache b/modules/swagger-codegen/src/main/resources/pkmst/optionalDataType.mustache new file mode 100644 index 00000000000..976950e27e8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/optionalDataType.mustache @@ -0,0 +1 @@ +{{#useOptional}}{{#required}}{{{dataType}}}{{/required}}{{^required}}Optional<{{{dataType}}}>{{/required}}{{/useOptional}}{{^useOptional}}{{{dataType}}}{{/useOptional}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pathParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pathParams.mustache new file mode 100644 index 00000000000..62342d01bfa --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}{{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}} {{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @PathVariable("{{baseName}}") {{>optionalDataType}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pojo.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pojo.mustache new file mode 100644 index 00000000000..5830c643aeb --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/pojo.mustache @@ -0,0 +1,140 @@ +/** + * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + */{{#description}} +@ApiModel(description = "{{{description}}}"){{/description}} +{{#useBeanValidation}}@Validated{{/useBeanValidation}} +{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#serializableModel}}implements Serializable{{/serializableModel}} { +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} +{{>enumClass}} + {{/isContainer}} + {{/isEnum}} + {{#items.isEnum}} + {{#items}} + {{^isContainer}} +{{>enumClass}} + {{/isContainer}} + {{/items}} + {{/items.isEnum}} + {{#jackson}} + @JsonProperty("{{baseName}}"){{#withXml}} + @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}"){{/withXml}} + {{/jackson}} + {{#gson}} + @SerializedName("{{baseName}}") + {{/gson}} + {{#isContainer}} + {{#useBeanValidation}}@Valid{{/useBeanValidation}} + private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}}; + {{/isContainer}} + + {{/vars}} + {{#vars}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + return this; + } + {{#isListContainer}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + } + {{/isListContainer}} + {{#isMapContainer}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + } + {{/isMapContainer}} + + /** + {{#description}} + * {{{description}}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ + {{#vendorExtensions.extraAnnotation}} + {{{vendorExtensions.extraAnnotation}}} + {{/vendorExtensions.extraAnnotation}} + @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}") +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + } + + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + } + + {{/vars}} + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}Objects.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return true;{{/hasVars}} + } + + @Override + public int hashCode() { + return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} + {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}}sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pojo_doc.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pojo_doc.mustache new file mode 100644 index 00000000000..0e4c0749866 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/pojo_doc.mustache @@ -0,0 +1,15 @@ +# {{classname}} + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} +{{/vars}} +{{#vars}}{{#isEnum}} + + +## Enum: {{datatypeWithEnum}} +Name | Value +---- | -----{{#allowableValues}}{{#enumVars}} +{{name}} | {{value}}{{/enumVars}}{{/allowableValues}} +{{/isEnum}}{{/vars}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache new file mode 100644 index 00000000000..d1f7c311ea9 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache @@ -0,0 +1,442 @@ + + + 4.0.0 + {{groupId}} + {{artifactId}} + {{artifactVersion}} + jar + {{artifactId}} + Demo project for Spring Boot Microservices + + UTF-8 + UTF-8 + 1.8 + 1.5.6.RELEASE + 1.2.5 + 1.2.5 + 3.10.0 + 2.6.1-SNAPSHOT + 2.6.0 + 1.7.25 + 4.11 + 1.2.3 + 1.2.3 + 2.3.0 + 2.2.4 + 3.2.2 + Camden.SR7 + 1.1.3.RELEASE + + + org.springframework.boot + spring-boot-starter-parent + 1.5.6.RELEASE + + + + + + oss-snapshots + JFrog OSS Snapshots + https://oss.jfrog.org/simple/oss-snapshot-local/ + + true + + + + central + Maven Repository Switchboard + default + http://repo1.maven.org/maven2 + + false + + + + jitpack.io + https://jitpack.io + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.assertj + assertj-core + + {{#eurekaUri}} + + org.springframework.cloud + spring-cloud-starter-eureka + + + org.springframework.cloud + spring-cloud-starter-eureka-server + + {{/eurekaUri}} + + {{#zipkinUri}} + + org.springframework.cloud + spring-cloud-starter-zipkin + + {{/zipkinUri}} + + + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-jetty + + + + org.springframework.cloud + spring-cloud-starter-hystrix-dashboard + + + org.springframework + spring-jdbc + + {{#springBootAdminUri}} + + de.codecentric + spring-boot-admin-starter-client + 1.2.4 + + {{/springBootAdminUri}} + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + com.netflix.hystrix + hystrix-javanica + 1.4.1 + + + org.apache.commons + commons-lang3 + 3.4 + + + commons-logging + commons-logging + 1.2 + + {{#pkmstInterceptor}} + + + com.github.rkumar-pk + pkmst-extension + 1.0.1 + + {{/pkmstInterceptor}} + + + info.cukes + cucumber-junit + ${cucumber-junit.version} + + + info.cukes + cucumber-java + ${cucumber-java.version} + + + info.cukes + cucumber-spring + ${cucumber-java.version} + + + net.masterthought + cucumber-reporting + ${cucumber-reporting.version} + + + com.github.tomakehurst + wiremock + 1.46 + test + + + io.springfox + springfox-swagger2 + ${springfox-swagger2} + + + io.springfox + springfox-swagger-ui + ${springfox-swagger-ui} + + + org.slf4j + slf4j-api + ${slf4j-api} + + + net.logstash.logback + logstash-logback-encoder + ${logstash-logback-encoder} + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-classic + + + org.springframework.boot + spring-boot-starter-remote-shell + + + org.jolokia + jolokia-core + + + + io.gatling.highcharts + gatling-charts-highcharts + ${gatling.version} + test + + + com.typesafe + config + 1.3.1 + + + com.jayway.restassured + rest-assured + 2.9.0 + + + org.springframework + spring-test + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + development + + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + + **/*CucumberTest*.java + + **/cucumber/*.java + + + + + + net.alchim31.maven + scala-maven-plugin + ${scala-maven-plugin.version} + + + + + org.springframework.boot + spring-boot-maven-plugin + + ${project.name} + + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + ${basedir}/target/coverage-reports/jacoco-unit.exec + ${basedir}/target/coverage-reports/jacoco-unit.exec + + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + test + + report + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.5.1 + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.4 + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.19.1 + + + org.apache.maven.plugins + maven-pmd-plugin + + + + + + + + + cucumber-tests + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + none + + + + {{serverName}}Test.java + + + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.springframework.cloud + spring-cloud-contract-maven-plugin + [1.0.1.RELEASE,) + + convert + generateTests + + + + + + + + + + + + + + diff --git a/modules/swagger-codegen/src/main/resources/pkmst/queryParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/queryParams.mustache new file mode 100644 index 00000000000..182152c6e5a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, allowableValues = "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue = "{{{defaultValue}}}"{{/defaultValue}}) {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestParam(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{>optionalDataType}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache new file mode 100644 index 00000000000..e803d782c37 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache @@ -0,0 +1,121 @@ +This is the sample Pkmst microservice template project generated from swagger codegen.Using swagger specification you can convert any definition to spring boot microservice. +It has the integration with the below services: +eureka registry, zipkin , spring boot admin, circuit breaker. + +By default only the circuit breaker annotation is enabled. But one has to write the fallback method. The needed dependency for it is also been enabled. To generate the integration and +related configuration for eureka, zipkin, spring boot admin one has two options: + +1) When generating from UI one has to provide vendor extensions inside the swagger specification as below: +swagger: "2.0" +info: + description: "This is a sample Product Catalogue Server.\ + \ For this sample, you can use the api key `special-key` to test the authorization\ + \ filters." + version: "1.0.0" + x-codegen: + eurekaUri: "http://localhost:8080" + zipkinUri: "http://localhost:9411" + springBootAdminUri: "http://localhost:8000" + pkmstInterceptor: "true" + +PLease note the vendor extensions are inside the info tag of the swagger specification. All the tags are case sensitive. Once given all the related configuration and the dependency +will be enabled. + +2) When generating from the maven plugin one has to provide configuration inside pom as below: +inside the swagger codegen maven plugin under the configuration section + + + product-swagger.yaml + pkmst + ${project.build.directory}/generated-sources + + com.prokarma + product-catalogue + 1.0 + com.prokarma.pkmst + ProductCatalogue + + http://localhost:9411 + http://localhost:4588 + true + + + + The project has three profiles local, dev, dev-config which can be configured accordingly. Once you have provided the uris you can see the necessary configurations generated inside the local and the dev + yml files. dev-config is for the config server if you want to use.(also enable the dependency for the config server inside the pom) + + [Note: one has to run the zipkin, eureka, spring boot admin servers to be able to connect from the app. This project assumes that you have all the servers + up and running.] + + Also provided are the middleware handlers: + +1) traceInterceptor:is an id passed in from client and will be unique with an application context. The id will be passed into the backend and return to the consumer for transaction tracing. + +2) correlationInterceptor:generates a UUID in the first API/service and pass it to all other APIs/services in the call tree for tracking purpose. + +3) rateLimitInterceptor:is a rate limiting handler to limit number of concurrent requests on the server. Once the limit is reached, subsequent requests will be queued for later execution. The size of the queue is configurable. + +4) auditInterceptor: audit logs most important info about request and response into audit.log in JSON format with config file that controls which fields to be logged + +5) bodyInterceptor:s a body parser middleware that is responsible for parsing the content of the request based on Content-Type in the request header. + +To be able to generate the handlers and the necessary configurations one has to provide the pkmstInterceptor key inside the vendor extensions or through +the maven plugin. +Once provided all the handlers are registered in the interceptor registry and can be enabled or disabled through the configuration provided inside +the application yml as below: +interceptor: + enable: + audit: true + body: true + rateLimit: true + traceability: true + correlation: true + +For testing we have placeholders for junit test class, integration test class, cucumber sample +feature file(implement according to your needs), gatling load test. + + + + + +Ways to run the project: +1) Normal spring boot application + +2) Using Dockerfile to run in the container: +dockerfile will be generated inside the project by default. Image can be created using docker cli or through the maven plugin + + + + ... + + com.spotify + docker-maven-plugin + VERSION GOES HERE + + example + docker + + + / + ${project.build.directory} + ${project.build.finalName}.jar + + + + + ... + + + +Use manifest.yml file to push the application to the cloud. + +HttpLogging filter is provided for logging in the request and response. Can be found inside the com.prokarma.pkmst.logging package. +Spring security is also provided to secure the resources. Please modify according to your needs. + +First run: +Import the project in to the eclipse. Run the app as an spring boot application.The project will run on http://localhost:8008 +Swagger ui available on: +http://localhost:8008/swagger-ui.html +If all the configurations have been enabled(depending on the port) below are some of the URls to access: +eureka: http://localhost:8080 +zipkin: http://localhost:9411 diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev-config.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev-config.mustache new file mode 100644 index 00000000000..79292387bb5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev-config.mustache @@ -0,0 +1,7 @@ +#Enable cloud config. Also enable the dependency in pom + #cloud: + #config: + #uri: {{configUri}} + #fail-fast: true + #password: user + #username: user \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev.mustache new file mode 100644 index 00000000000..a8ad3b2a0a7 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-dev.mustache @@ -0,0 +1,78 @@ +# Discovery Server Access +{{#eurekaUri}} +eureka: + instance: + leaseRenewalIntervalInSeconds: 1 + leaseExpirationDurationInSeconds: 2 + hostname: localhost + healthCheckUrl: http://localhost:{{serverPort}}/health + nonSecurePort: 80 + client: + enabled: true + healthcheck: + enabled: true + registerWithEureka: true + #fetchRegistry: true + serviceUrl: + defaultZone: {{eurekaUri}}/eureka/ +{{/eurekaUri}} +server: + port: {{serverPort}} + +# Spring Actuator +management: + health: + redis: + enabled: false + security: + enabled: false + + +endpoints: + health: + sensitive: false + +info: + app: + name: {{serviceName}} + description: Microservice developed by PKMST + version: {{artifactVersion}} + +health: + hystrix: + enabled: true + +security: + basic: + enabled: false +# provide rabbitmq configuration +spring: + rabbitmq: + host: + virtual-host: + username: + password: + port: + {{#zipkinUri}} + zipkin: + base-url: {{zipkinUri}} + {{/zipkinUri}} + + {{#springBootAdminUri}} + boot: + admin: + url: {{springBootAdminUri}} + client: + health-url: http://localhost:{{serverPort}}/health + management-url: http://localhost:{{serverPort}} + service-url: http://localhost:{{serverPort}} + {{/springBootAdminUri}} + sleuth: + sampler: + percentage: 1.0 +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/application-local.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-local.mustache new file mode 100644 index 00000000000..b8025d85db2 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/application-local.mustache @@ -0,0 +1,87 @@ +# Discovery Server Access +{{#eurekaUri}} +eureka: + instance: + leaseRenewalIntervalInSeconds: 1 + leaseExpirationDurationInSeconds: 2 + hostname: localhost + healthCheckUrl: http://localhost:{{serverPort}}/health + nonSecurePort: 80 + client: + enabled: true + healthcheck: + enabled: true + registerWithEureka: true + #fetchRegistry: true + serviceUrl: + defaultZone: {{eurekaUri}}/eureka/ +{{/eurekaUri}} +server: + port: {{serverPort}} + +# Spring Actuator +management: + health: + redis: + enabled: false + security: + enabled: false + + +endpoints: + health: + sensitive: false + +info: + app: + name: {{serviceName}} + description: Microservice developed by PKMST + version: {{artifactVersion}} + +health: + hystrix: + enabled: true + +security: + basic: + enabled: false +# provide rabbitmq configuration +spring: + rabbitmq: + host: + virtual-host: + username: + password: + port: + {{#zipkinUri}} + zipkin: + base-url: {{zipkinUri}} + {{/zipkinUri}} + + {{#springBootAdminUri}} + boot: + admin: + url: {{springBootAdminUri}} + client: + health-url: http://localhost:{{serverPort}}/health + management-url: http://localhost:{{serverPort}} + service-url: http://localhost:{{serverPort}} + {{/springBootAdminUri}} + sleuth: + sampler: + percentage: 1.0 +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG +{{#pkmstInterceptor}} +interceptor: + enable: + audit: true + body: true + rateLimit: true + traceability: true + correlation: true +{{/pkmstInterceptor}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/application.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/application.mustache new file mode 100644 index 00000000000..e686a5a0c33 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/application.mustache @@ -0,0 +1,5 @@ +springfox.documentation.swagger.v2.path=/api-docs +server.contextPath={{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}} +server.port={{serverPort}} +spring.jackson.date-format={{basePackage}}.RFC3339DateFormat +spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/resources/bootstrap.mustache b/modules/swagger-codegen/src/main/resources/pkmst/resources/bootstrap.mustache new file mode 100644 index 00000000000..2f125971180 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/resources/bootstrap.mustache @@ -0,0 +1,5 @@ +spring: + application: + name: {{artifactId}} + profiles: + active: local \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/returnTypes.mustache b/modules/swagger-codegen/src/main/resources/pkmst/returnTypes.mustache new file mode 100644 index 00000000000..c8f7a56938a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/returnTypes.mustache @@ -0,0 +1 @@ +{{#returnContainer}}{{#isMapContainer}}Map{{/isMapContainer}}{{#isListContainer}}List<{{{returnType}}}>{{/isListContainer}}{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/security/authorizationServerConfiguration.mustache b/modules/swagger-codegen/src/main/resources/pkmst/security/authorizationServerConfiguration.mustache new file mode 100644 index 00000000000..8db45c3b578 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/security/authorizationServerConfiguration.mustache @@ -0,0 +1,61 @@ +package {{basePackage}}.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; +import org.springframework.security.oauth2.provider.token.TokenStore; +/** + * Convenient strategy for configuring an OAUth2 Authorization Server. Beans of this type are applied to the Spring + * context automatically if you {@link EnableAuthorizationServer @EnableAuthorizationServer}. + * + * @author pkmst + * + */ +@Configuration +@EnableAuthorizationServer +public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { + + private static String REALM="MY_OAUTH_REALM"; + + @Autowired + private TokenStore tokenStore; + + @Autowired + private UserApprovalHandler userApprovalHandler; + + @Autowired + @Qualifier("authenticationManagerBean") + private AuthenticationManager authenticationManager; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .secret("secret") + .accessTokenValiditySeconds(120).//Access token is only valid for 2 minutes. + refreshTokenValiditySeconds(600);//Refresh token is only valid for 10 minutes. + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler) + .authenticationManager(authenticationManager); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.realm(REALM+"/client"); + } + +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/security/oAuth2SecurityConfiguration.mustache b/modules/swagger-codegen/src/main/resources/pkmst/security/oAuth2SecurityConfiguration.mustache new file mode 100644 index 00000000000..a84cd0ba579 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/security/oAuth2SecurityConfiguration.mustache @@ -0,0 +1,82 @@ +package {{basePackage}}.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.core.annotation.Order; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +/** + * Provides a convenient base class for creating a {@link WebSecurityConfigurer} + * instance. The implementation allows customization by overriding methods. + * + * @see EnableWebSecurity + * + * @author pkmst + */ +@Configuration +@EnableWebSecurity +@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) +public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("admin").password("admin@123").roles("ADMIN").and() + .withUser("user").password("user@123").roles("USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable() + .anonymous().disable() + .authorizeRequests() + .antMatchers("/oauth/token").permitAll(); + } + + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + + @Bean + public TokenStore tokenStore() { + return new InMemoryTokenStore(); + } + + @Bean + @Autowired + public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){ + TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); + handler.setTokenStore(tokenStore); + handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); + handler.setClientDetailsService(clientDetailsService); + return handler; + } + + @Bean + @Autowired + public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception { + TokenApprovalStore store = new TokenApprovalStore(); + store.setTokenStore(tokenStore); + return store; + } + +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/security/resourceServerConfiguration.mustache b/modules/swagger-codegen/src/main/resources/pkmst/security/resourceServerConfiguration.mustache new file mode 100644 index 00000000000..654fa148910 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/security/resourceServerConfiguration.mustache @@ -0,0 +1,42 @@ +package {{basePackage}}.security; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.http.HttpMethod; +/** + * Configurer class for @EnableResourceServer classes. This class adjust the access + * rules and paths that are protected by OAuth2 security. If more than one configures the same property, then the last + * one wins. The configurers are sorted by {@link Order} before being applied. + * + * @author pkmst + * + */ +@Configuration +@EnableResourceServer +public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { + + private static final String RESOURCE_ID = "my_rest_api"; + + @Override + public void configure(ResourceServerSecurityConfigurer resources) { + resources.resourceId(RESOURCE_ID).stateless(false); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + //configure security for the http methods + {{#resourcePaths}} + http. + anonymous().disable() + .requestMatchers().antMatchers(HttpMethod.GET, "/{{path}}/**") + .and().authorizeRequests() + .antMatchers(HttpMethod.GET, "/{{path}}/**").access("hasRole('ADMIN')") + .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); + {{/resourcePaths}} + } + +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/testresources/application-test.mustache b/modules/swagger-codegen/src/main/resources/pkmst/testresources/application-test.mustache new file mode 100644 index 00000000000..5b21a67c370 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/testresources/application-test.mustache @@ -0,0 +1,4 @@ +server.port = 8081 +{{#eurekaUri}} +eureka.client.enabled=false +{{/eurekaUri}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/testresources/application.mustache b/modules/swagger-codegen/src/main/resources/pkmst/testresources/application.mustache new file mode 100644 index 00000000000..5b21a67c370 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/testresources/application.mustache @@ -0,0 +1,4 @@ +server.port = 8081 +{{#eurekaUri}} +eureka.client.enabled=false +{{/eurekaUri}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/testresources/bootstrap.mustache b/modules/swagger-codegen/src/main/resources/pkmst/testresources/bootstrap.mustache new file mode 100644 index 00000000000..abde2ab27c5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/testresources/bootstrap.mustache @@ -0,0 +1,5 @@ +spring: + application: + name: {{artifactId}} + profiles: + active: test \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/xmlAnnotation.mustache b/modules/swagger-codegen/src/main/resources/pkmst/xmlAnnotation.mustache new file mode 100644 index 00000000000..fd81a4cf5d8 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/xmlAnnotation.mustache @@ -0,0 +1,6 @@ +{{#withXml}} +{{#jackson}} +@JacksonXmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +{{/jackson}} +@XmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +@XmlAccessorType(XmlAccessType.FIELD){{/withXml}} \ No newline at end of file From e185b7513f710a1b4333ab47199ce0e71f790085 Mon Sep 17 00:00:00 2001 From: rkumar-pk Date: Wed, 22 Nov 2017 17:28:56 +0530 Subject: [PATCH 02/19] formatted --- .../codegen/languages/PkmstServerCodegen.java | 2788 ++++++++--------- 1 file changed, 1353 insertions(+), 1435 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java index 68cfff5d796..59b91e14de6 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java @@ -1,6 +1,5 @@ package io.swagger.codegen.languages; - import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -47,1331 +46,1250 @@ */ public class PkmstServerCodegen extends DefaultCodegen implements CodegenConfig { - public static final String FULL_JAVA_UTIL = "fullJavaUtil"; - public static final String SUPPORT_JAVA6 = "supportJava6"; - public static final String CONFIG_PACKAGE = "configPackage"; - public static final String BASE_PACKAGE = "basePackage"; - public static final String TITLE = "title"; - public static final String WITH_XML = "withXml"; - public static final String EUREKA_URI = "eurekaUri"; - public static final String ZIPKIN_URI = "zipkinUri"; - public static final String SPRINGADMIN_URI = "springBootAdminUri"; - protected String groupId = "com.prokarma"; - protected String artifactId = "pkmst-microservice"; - protected String artifactVersion = "1.0.0"; - protected String projectFolder; - - -protected String projectTestFolder; - protected String sourceFolder; - protected String testFolder; - protected String basePackage = "com.prokarma.pkmst"; - protected String serviceName = "Pkmst"; - protected String configPackage = "com.prokarma.pkmst.config"; - protected boolean implicitHeaders = false; - protected boolean serializeBigDecimalAsString = false; - protected boolean withXml = false; - protected boolean fullJavaUtil; - protected String javaUtilPrefix = ""; - protected Boolean serializableModel = false; - protected String invokerPackage; - protected String title; - protected String apiDocPath = "docs/"; - protected String modelDocPath = "docs/"; - protected String eurekaUri; - protected String zipkinUri; - protected String springBootAdminUri; - - public PkmstServerCodegen() { - super(); - this.projectFolder = "src" + File.separator + "main"; - this.projectTestFolder = "src" + File.separator + "test"; - this.sourceFolder = this.projectFolder + File.separator + "java"; - this.testFolder = this.projectTestFolder + File.separator + "java"; - embeddedTemplateDir = templateDir = "pkmst"; - apiPackage = "com.prokarma.pkmst.controller"; - modelPackage = "com.prokarma.pkmst.model"; - invokerPackage = "com.prokarma.pkmst.controller"; - setReservedWordsLowerCase( - Arrays.asList( - // used as internal variables, can collide with parameter names - "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", - "localVarHeaderParams", "localVarFormParams", "localVarPostBody", - "localVarAccepts", "localVarAccept", "localVarContentTypes", - "localVarContentType", "localVarAuthNames", "localReturnType", - "ApiClient", "ApiException", "ApiResponse", "Configuration", "StringUtil", - - // language reserved words - "abstract", "continue", "for", "new", "switch", "assert", - "default", "if", "package", "synchronized", "boolean", "do", "goto", "private", - "this", "break", "double", "implements", "protected", "throw", "byte", "else", - "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", - "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", - "void", "class", "finally", "long", "strictfp", "volatile", "const", "float", - "native", "super", "while", "null") - ); - - this.languageSpecificPrimitives = new HashSet( - Arrays.asList( - "String", - "boolean", - "Boolean", - "Double", - "Integer", - "Long", - "Float", - "Object", - "byte[]") - ); - this.instantiationTypes.put("array", "ArrayList"); - this.instantiationTypes.put("map", "HashMap"); - this.typeMapping.put("date", "Date"); - this.typeMapping.put("file", "File"); - - this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); - this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); - this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); - this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); - this.cliOptions.add(new CliOption("serviceName", "Service Name")); - this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); - this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); - this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); - this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); - //Middleware config - this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); - this.apiTestTemplateFiles.put("api_test.mustache", ".java"); - this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); - this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); - } - - private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, - CodegenModel parentCodegenModel) { - // This generator uses inline classes to define enums, which breaks when - // dealing with models that have subTypes. To clean this up, we will analyze - // the parent and child models, look for enums that match, and remove - // them from the child models and leave them in the parent. - // Because the child models extend the parents, the enums will be available via the parent. - - // Only bother with reconciliation if the parent model has enums. - if (!parentCodegenModel.hasEnums) { - return codegenModel; - } - - // Get the properties for the parent and child models - final List parentModelCodegenProperties = parentCodegenModel.vars; - List codegenProperties = codegenModel.vars; - - // Iterate over all of the parent model properties - boolean removedChildEnum = false; - for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { - // Look for enums - if (parentModelCodegenPropery.isEnum) { - // Now that we have found an enum in the parent class, - // and search the child class for the same enum. - Iterator iterator = codegenProperties.iterator(); - while (iterator.hasNext()) { - CodegenProperty codegenProperty = iterator.next(); - if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { - // We found an enum in the child class that is - // a duplicate of the one in the parent, so remove it. - iterator.remove(); - removedChildEnum = true; - } - } - } - } - - if (removedChildEnum) { - // If we removed an entry from this model's vars, we need to ensure hasMore is updated - int count = 0, numVars = codegenProperties.size(); - for (CodegenProperty codegenProperty : codegenProperties) { - count += 1; - codegenProperty.hasMore = (count < numVars) ? true : false; - } - codegenModel.vars = codegenProperties; - } - return codegenModel; - } - - private static String getAccept(Operation operation) { - String accepts = null; - String defaultContentType = "application/json"; - if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (String produces : operation.getProduces()) { - if (defaultContentType.equalsIgnoreCase(produces)) { - accepts = defaultContentType; - break; - } else { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(produces); - } - } - if (accepts == null) { - accepts = sb.toString(); - } - } else { - accepts = defaultContentType; - } - - return accepts; - } - - public CodegenType getTag() { - return CodegenType.SERVER; - } - - public String getName() { - return "pkmst"; - } - - public String getHelp() { - return "Generates a Java SpringBoot Server application using the SpringFox integration." - + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; - } - - public void processOpts() { - super.processOpts(); - if (this.additionalProperties.containsKey("basePackage")) { - this.setBasePackage((String) this.additionalProperties.get("basePackage")); - this.setInvokerPackage(this.getBasePackage()); - this.apiPackage = this.getBasePackage() + ".controller"; - this.modelPackage = this.getBasePackage() + ".model"; - this.setConfigPackage(this.getBasePackage() + ".config"); - - //this.additionalProperties.put(BASE_PACKAGE, this.getBasePackage()); - }else{ - this.additionalProperties.put(BASE_PACKAGE, basePackage); - this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); - this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); - this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); - this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); - } - if (this.additionalProperties.containsKey("groupId")) { - this.setGroupId((String) this.additionalProperties.get("groupId")); - }else { - //not set, use to be passed to template - additionalProperties.put(CodegenConstants.GROUP_ID, groupId); - } - if (this.additionalProperties.containsKey("artifactId")) { - this.setArtifactId((String) this.additionalProperties.get("artifactId")); - }else { - //not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); - } - if (this.additionalProperties.containsKey("artifactVersion")) { - this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); - }else { - //not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); - } - if (this.additionalProperties.containsKey("serviceName")) { - this.setServiceName((String) this.additionalProperties.get("serviceName")); - } - else { - //not set, use to be passed to template - additionalProperties.put("serviceName", serviceName); - } - - if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { - this.setSerializeBigDecimalAsString(Boolean.valueOf( - this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING) - .toString())); - } - if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { - this.setSerializableModel(Boolean - .valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); - } - if (this.additionalProperties.containsKey(TITLE)) { - this.setTitle((String) this.additionalProperties.get(TITLE)); - } - this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); - if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { - this.setFullJavaUtil( - Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); - } - - if (this.additionalProperties.containsKey(EUREKA_URI)) { - this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); - } - if (this.additionalProperties.containsKey(ZIPKIN_URI)) { - this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); - } - if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { - this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); - } - if (fullJavaUtil) { - javaUtilPrefix = "java.util."; - } - this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); - this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); - this.additionalProperties.put(SUPPORT_JAVA6, false); - this.additionalProperties.put("java8", true); - - if (this.additionalProperties.containsKey(WITH_XML)) { - this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); - } - this.additionalProperties.put(WITH_XML, withXml); - - // make api and model doc path available in mustache template - this.additionalProperties.put("apiDocPath", apiDocPath); - this.additionalProperties.put("modelDocPath", modelDocPath); - - this.importMapping.put("List", "java.util.List"); - - if (fullJavaUtil) { - this.typeMapping.put("array", "java.util.List"); - this.typeMapping.put("map", "java.util.Map"); - this.typeMapping.put("DateTime", "java.util.Date"); - this.typeMapping.put("UUID", "java.util.UUID"); - this.typeMapping.remove("List"); - this.importMapping.remove("Date"); - this.importMapping.remove("Map"); - this.importMapping.remove("HashMap"); - this.importMapping.remove("Array"); - this.importMapping.remove("ArrayList"); - this.importMapping.remove("List"); - this.importMapping.remove("Set"); - this.importMapping.remove("DateTime"); - this.importMapping.remove("UUID"); - this.instantiationTypes.put("array", "java.util.ArrayList"); - this.instantiationTypes.put("map", "java.util.HashMap"); - } - // optional jackson mappings for BigDecimal support - this.importMapping - .put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); - this.importMapping - .put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); - - // imports for pojos - this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); - this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); - this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); - this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); - this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); - this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); - this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); - this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); - this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); - this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); - this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); - this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); - this.importMapping.put("IOException", "java.io.IOException"); - this.importMapping.put("Objects", "java.util.Objects"); - this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); - // import JsonCreator if JsonProperty is imported - // used later in recursive import in postProcessingModels - this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", - "com.fasterxml.jackson.annotation.JsonCreator"); - - this.apiTemplateFiles.put("api.mustache", ".java"); - this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); - - this.modelTemplateFiles.put("model.mustache", ".java"); - - this.supportingFiles.add(new SupportingFile( - "SpringBootApplication.mustache", - (this.getSourceFolder() + File.separator + this.getBasePackage()) - .replace(".", File.separator), - this.getServiceName() + "Application" + ".java")); - - this.supportingFiles.add(new SupportingFile( - "config" + File.separator + "swaggerDocumentationConfig.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()) - .replace(".", java.io.File.separator) + File.separator + "swagger", - "SwaggerDocumentationConfig.java")); - - this.supportingFiles.add(new SupportingFile( - "config" + File.separator + "pkmstproperties.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()) - .replace(".", java.io.File.separator) + File.separator + "swagger", - "PkmstProperties.java")); - this.supportingFiles.add(new SupportingFile( - "config" + File.separator + "appconfig.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()) - .replace(".", java.io.File.separator) + File.separator, - "AppConfig.java")); - - // Security - this.supportingFiles.add(new SupportingFile( - "security" + File.separator + "authorizationServerConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "AuthorizationServerConfiguration.java" - )); - this.supportingFiles.add(new SupportingFile( - "security" + File.separator + "oAuth2SecurityConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "OAuth2SecurityConfiguration.java" - )); - this.supportingFiles.add(new SupportingFile( - "security" + File.separator + "resourceServerConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "ResourceServerConfiguration.java" - )); - - // logging - - this.supportingFiles.add(new SupportingFile( - "logging" + File.separator + "httpLoggingFilter.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "logging", - "HttpLoggingFilter.java" - )); - - // Resources - this.supportingFiles.add(new SupportingFile( - "resources" + File.separator + "application-local.mustache", - ("src.main.resources").replace(".", java.io.File.separator), - "application-local.yml")); - this.supportingFiles.add(new SupportingFile( - "resources" + File.separator + "application-dev.mustache", - ("src.main.resources").replace(".", java.io.File.separator), - "application-dev.yml")); - this.supportingFiles.add(new SupportingFile( - "resources" + File.separator + "application-dev-config.mustache", - ("src.main.resources").replace(".", java.io.File.separator), - "application-dev-config.yml")); - this.supportingFiles.add(new SupportingFile( - "resources" + File.separator + "bootstrap.mustache", - ("src.main.resources").replace(".", java.io.File.separator), - "bootstrap.yml")); - - // POM - this.supportingFiles.add(new SupportingFile( - "pom.mustache", - "", - "pom.xml")); - - //Readme - this.supportingFiles.add(new SupportingFile( - "readme.mustache", - "", - "Readme.md")); - - //manifest - - this.supportingFiles.add(new SupportingFile( - "manifest.mustache", - "", - "manifest.yml")); - - //docker - this.supportingFiles.add(new SupportingFile( - "docker.mustache", - "", - "Dockerfile")); - - //logstash - - this.supportingFiles.add(new SupportingFile( - "logstash.mustache", - "", - "logstash.conf")); - - // Cucumber - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "executeReport.mustache", - this.testFolder + File.separator + this.basePackage .replace(".", File.separator) - + File.separator +"cucumber" + File.separator+"report", - "ExecuteReport.java" - )); - - - - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "cucumberTest.mustache", - this.testFolder + File.separator + this.basePackage .replace(".", File.separator) - + File.separator +"cucumber", - serviceName + "Test.java" - )); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "cucumberSteps.mustache", - this.testFolder + File.separator + this.basePackage .replace(".", File.separator) - + File.separator +"cucumber", - serviceName + "Steps.java" - )); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "package.mustache", - this.testFolder + File.separator + this.basePackage .replace(".", File.separator) - + File.separator +"cucumber", - serviceName + "package-info.java" - )); - - //test resources - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "cucumber.mustache", - (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "cucumber", - serviceName+".feature" - )); - - this.supportingFiles.add(new SupportingFile( - "testresources" + File.separator + "bootstrap.mustache", - ("src.test.resources").replace(".", java.io.File.separator), - "bootstrap.yml")); - this.supportingFiles.add(new SupportingFile( - "testresources" + File.separator + "application.mustache", - ("src.test.resources").replace(".", java.io.File.separator), - "application.properties")); - this.supportingFiles.add(new SupportingFile( - "testresources" + File.separator + "application-test.mustache", - ("src.test.resources").replace(".", java.io.File.separator), - "application-test.properties")); - - //Gatling - this.supportingFiles.add(new SupportingFile( - "gatling" + File.separator + "gatling.mustache", - ("src.test.resources").replace(".", java.io.File.separator), - "gatling.conf")); - - - this.supportingFiles.add(new SupportingFile( - "gatling" + File.separator + "application.mustache", - ("src.test.resources").replace(".", java.io.File.separator), - "application.conf")); - - this.supportingFiles.add(new SupportingFile( - "gatling" + File.separator + "testapi.mustache", - ("src")+ File.separator + ("test")+ File.separator + ("scala")+ File.separator + ("scalaFiles").replace(".", java.io.File.separator), - "testapi.scala")); - - /*this.supportingFiles.add(new SupportingFile( - "gatling" + File.separator + "package.mustache", - ("src")+ File.separator + ("test")+ File.separator + ("scala")+ File.separator + ("scalaFiles").replace(".", java.io.File.separator), - "package.info"));*/ - - // adding class for integration test - this.supportingFiles.add(new SupportingFile( - "integration" + File.separator + "integrationtest.mustache", - this.testFolder + File.separator + this.basePackage .replace(".", File.separator) - + File.separator +"controller", - serviceName + "IT.java" - )); - } - - @Override - public Map postProcessOperations(Map objs) { - Map operations = (Map) objs.get("operations"); - if (operations != null) { - List ops = (List) operations.get("operation"); - for (final CodegenOperation operation : ops) { - List responses = operation.responses; - if (responses != null) { - for (final CodegenResponse resp : responses) { - if ("0".equals(resp.code)) { - resp.code = "200"; - } - doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { - - public void setReturnType(final String returnType) { - resp.dataType = returnType; - } - - public void setReturnContainer(final String returnContainer) { - resp.containerType = returnContainer; - } - }); - } - } - - doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { - - public void setReturnType(final String returnType) { - operation.returnType = returnType; - } - - public void setReturnContainer(final String returnContainer) { - operation.returnContainer = returnContainer; - } - }); - - if (implicitHeaders) { - removeHeadersFromAllParams(operation.allParams); - } - } - } - - return objs; - } - - /** - * This method removes header parameters from the list of parameters and also - * corrects last allParams hasMore state. - * - * @param allParams list of all parameters - */ - private void removeHeadersFromAllParams(List allParams) { - if (allParams.isEmpty()) { - return; - } - final ArrayList copy = new ArrayList(allParams); - allParams.clear(); - - for (CodegenParameter p : copy) { - if (!p.isHeaderParam) { - allParams.add(p); - } - } - allParams.get(allParams.size() - 1).hasMore = false; - } - - /** - * @param returnType The return type that needs to be converted - * @param dataTypeAssigner An object that will assign the data to the respective fields in the - * model. - */ - private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { - final String rt = returnType; - if (rt == null) { - dataTypeAssigner.setReturnType("Void"); - } else if (rt.startsWith("List")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); - dataTypeAssigner.setReturnContainer("List"); - } - } else if (rt.startsWith("Map")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); - dataTypeAssigner.setReturnContainer("Map"); - } - } else if (rt.startsWith("Set")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); - dataTypeAssigner.setReturnContainer("Set"); - } - } - } - - @Override - public String getSwaggerType(Property p) { - String swaggerType = super.getSwaggerType(p); - - swaggerType = getAlias(swaggerType); - - // don't apply renaming on types from the typeMapping - if (this.typeMapping.containsKey(swaggerType)) { - return this.typeMapping.get(swaggerType); - } - - if (null == swaggerType) { - LOGGER.error("No Type defined for Property " + p); - } - return toModelName(swaggerType); - } - - @Override - public String getAlias(String name) { - if (typeAliases.containsKey(name)) { - return typeAliases.get(name); - } - return name; - } - - @Override - public String toModelName(final String name) { - // We need to check if import-mapping has a different model for this class, so we use it - // instead of the auto-generated one. - if (this.importMapping.containsKey(name)) { - return this.importMapping.get(name); - } - - final String sanitizedName = sanitizeName(name); - - String nameWithPrefixSuffix = sanitizedName; - if (!StringUtils.isEmpty(modelNamePrefix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; - } - - if (!StringUtils.isEmpty(modelNameSuffix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; - } - - // camelize the model name - // phone_number => PhoneNumber - final String camelizedName = camelize(nameWithPrefixSuffix); - - // model name cannot use reserved keyword, e.g. return - if (isReservedWord(camelizedName)) { - final String modelName = "Model" + camelizedName; - LOGGER.warn( - camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); - return modelName; - } - - // model name starts with number - if (camelizedName.matches("^\\d.*")) { - final String modelName = - "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize) - LOGGER.warn( - name + " (model name starts with number) cannot be used as model name. Renamed to " - + modelName); - return modelName; - } - - return camelizedName; - } - - @Override - public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - if (serializeBigDecimalAsString) { - if (property.baseType.equals("BigDecimal")) { - // we serialize BigDecimal as `string` to avoid precision loss - property.vendorExtensions - .put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); - - // this requires some more imports to be added for this model... - model.imports.add("ToStringSerializer"); - model.imports.add("JsonSerialize"); - } - } - - if (!fullJavaUtil) { - if ("array".equals(property.containerType)) { - model.imports.add("ArrayList"); - } else if ("map".equals(property.containerType)) { - model.imports.add("HashMap"); - } - } - - if (!BooleanUtils.toBoolean(model.isEnum)) { - // needed by all pojos, but not enums - model.imports.add("ApiModelProperty"); - model.imports.add("ApiModel"); - } - - //super.postProcessModelProperty(model, property); - - if ("null".equals(property.example)) { - property.example = null; - } - - //Add imports for Jackson - if (!Boolean.TRUE.equals(model.isEnum)) { - model.imports.add("JsonProperty"); - - if (Boolean.TRUE.equals(model.hasEnums)) { - model.imports.add("JsonValue"); - } - } else { // enum class - //Needed imports for Jackson's JsonCreator - if (this.additionalProperties.containsKey("jackson")) { - model.imports.add("JsonCreator"); - } - } - } - - @Override - public Map postProcessModelsEnum(Map objs) { - objs = super.postProcessModelsEnum(objs); - - //Add imports for Jackson - List> imports = (List>) objs.get("imports"); - List models = (List) objs.get("models"); - for (Object _mo : models) { - Map mo = (Map) _mo; - CodegenModel cm = (CodegenModel) mo.get("model"); - // for enum model - if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { - cm.imports.add(this.importMapping.get("JsonValue")); - Map item = new HashMap(); - item.put("import", this.importMapping.get("JsonValue")); - imports.add(item); - } - } - - return objs; - } - - @Override - public CodegenModel fromModel(String name, Model model, Map allDefinitions) { - CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); - if (codegenModel.description != null) { - codegenModel.imports.add("ApiModel"); - } - if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { - codegenModel.imports.add("JsonSubTypes"); - codegenModel.imports.add("JsonTypeInfo"); - } - if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { - final Model parentModel = allDefinitions.get(codegenModel.parentSchema); - final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); - codegenModel = PkmstServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); - } - return codegenModel; - } - - @Override - public Map postProcessSupportingFileData(Map objs) { - return objs; - } - - @Override - public Map postProcessModels(Map objs) { - // recursively add import for mapping one type to multiple imports - List> recursiveImports = (List>) objs.get("imports"); - if (recursiveImports == null) { - return objs; - } - - ListIterator> listIterator = recursiveImports.listIterator(); - while (listIterator.hasNext()) { - String _import = listIterator.next().get("import"); - // if the import package happens to be found in the importMapping (key) - // add the corresponding import package to the list - if (importMapping.containsKey(_import)) { - Map newImportMap = new HashMap(); - newImportMap.put("import", importMapping.get(_import)); - listIterator.add(newImportMap); - } - } - - return postProcessModelsEnum(objs); - } - - @Override - public void preprocessSwagger(Swagger swagger) { - super.preprocessSwagger(swagger); - if (swagger == null || swagger.getPaths() == null) { - return; - } - if(swagger.getTags()!=null){ - System.out.println("Tags are::"+swagger.getTags()); - List resourcePaths = new ArrayList(); - for (Tag tag : swagger.getTags()) { - ResourcePath resourcePath = new ResourcePath(); - resourcePath.setPath(tag.getName()); - resourcePaths.add(resourcePath); - } - this.additionalProperties.put("resourcePaths", resourcePaths); - } - //get vendor extensions - - Map vendorExt = swagger.getInfo().getVendorExtensions(); - if(vendorExt !=null && !vendorExt.toString().equals("")){ - if(vendorExt.containsKey("x-codegen")){ - - Map uris = (Map) vendorExt.get("x-codegen"); - if(uris.containsKey("eurekaUri")){ - String eurekaUri = uris.get("eurekaUri"); - additionalProperties.put(EUREKA_URI,eurekaUri); - } - if(uris.containsKey("zipkinUri")){ - String zipkinUri = uris.get("zipkinUri"); - additionalProperties.put(ZIPKIN_URI, zipkinUri); - } - if(uris.containsKey("springBootAdminUri")){ - String springBootAdminUri = uris.get("springBootAdminUri"); - additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); - } - if(uris.containsKey("pkmstInterceptor")){ - String pkmstInterceptor = uris.get("pkmstInterceptor"); - additionalProperties.put("pkmstInterceptor", pkmstInterceptor); - } - } - } - - - - for (String pathname : swagger.getPaths().keySet()) { - Path path = swagger.getPath(pathname); - if (path.getOperations() == null) { - continue; - } - for (Operation operation : path.getOperations()) { - boolean hasFormParameters = false; - for (Parameter parameter : operation.getParameters()) { - if (parameter instanceof FormParameter) { - hasFormParameters = true; - } - } - //only add content-Type if its no a GET-Method - if (path.getGet() != null || !operation.equals(path.getGet())) { - String defaultContentType = - hasFormParameters ? "application/x-www-form-urlencoded" : "application/json"; - String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() - ? defaultContentType : operation.getConsumes().get(0); - operation.setVendorExtension("x-contentType", contentType); - } - String accepts = getAccept(operation); - operation.setVendorExtension("x-accepts", accepts); - } - } - - if ("/".equals(swagger.getBasePath())) { - swagger.setBasePath(""); - } - - if (!additionalProperties.containsKey(TITLE)) { - // From the title, compute a reasonable name for the package and the API - String title = swagger.getInfo().getTitle(); - - // Drop any API suffix - if (title != null) { - title = title.trim().replace(" ", "-"); - if (title.toUpperCase().endsWith("API")) { - title = title.substring(0, title.length() - 3); - } - - this.title = camelize(sanitizeName(title), true); - } - additionalProperties.put(TITLE, this.title); - } - - String host = swagger.getHost(); - String port = "8008"; - if (host != null) { - String[] parts = host.split(":"); - if (parts.length > 1) { - port = parts[1]; - } - } - - this.additionalProperties.put("serverPort", port); - if (swagger.getPaths() != null) { - for (String pathname : swagger.getPaths().keySet()) { - Path path = swagger.getPath(pathname); - if (path.getOperations() != null) { - for (Operation operation : path.getOperations()) { - if (operation.getTags() != null) { - List> tags = new ArrayList>(); - for (String tag : operation.getTags()) { - Map value = new HashMap(); - value.put("tag", tag); - value.put("hasMore", "true"); - tags.add(value); - } - if (tags.size() > 0) { - tags.get(tags.size() - 1).remove("hasMore"); - } - if (operation.getTags().size() > 0) { - String tag = operation.getTags().get(0); - operation.setTags(Arrays.asList(tag)); - } - operation.setVendorExtension("x-tags", tags); - } - } - } - } - } - } - - @Override - public void addOperationToGroup(String tag, String resourcePath, Operation operation, - CodegenOperation co, Map> operations) { - String basePath = resourcePath; - if (basePath.startsWith("/")) { - basePath = basePath.substring(1); - } - int pos = basePath.indexOf("/"); - if (pos > 0) { - basePath = basePath.substring(0, pos); - } - - if (basePath.equals("")) { - basePath = "default"; - } else { - co.subresourceOperation = !co.path.isEmpty(); - } - List opList = operations.get(basePath); - if (opList == null) { - opList = new ArrayList(); - operations.put(basePath, opList); - } - opList.add(co); - co.baseName = basePath; - } - - @Override - public String toApiName(String name) { - if (name.length() == 0) { - return "DefaultApi"; - } - name = sanitizeName(name); - return camelize(name) + "Api"; - } - - @Override - public void setParameterExampleValue(CodegenParameter p) { - String type = p.baseType; - if (type == null) { - type = p.dataType; - } - - if ("File".equals(type)) { - String example; - - if (p.defaultValue == null) { - example = p.example; - } else { - example = p.defaultValue; - } - - if (example == null) { - example = "/path/to/file"; - } - example = - "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText( - example) + "\"))"; - p.example = example; - } else { - super.setParameterExampleValue(p); - } - } - - @Override - public String escapeReservedWord(String name) { - if (this.reservedWordsMappings().containsKey(name)) { - return this.reservedWordsMappings().get(name); - } - return "_" + name; - } - - @Override - public String apiFileFolder() { - return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); - } - - @Override - public String apiTestFileFolder() { - return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); - } - - @Override - public String modelFileFolder() { - return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); - } - - @Override - public String apiDocFileFolder() { - return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); - } - - @Override - public String modelDocFileFolder() { - return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); - } - - @Override - public String toVarName(String name) { - // sanitize name - name = sanitizeName( - name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. - - if (name.toLowerCase().matches("^_*class$")) { - return "propertyClass"; - } - - if ("_".equals(name)) { - name = "_u"; - } - - // if it's all uppper case, do nothing - if (name.matches("^[A-Z_]*$")) { - return name; - } - - if (startsWithTwoUppercaseLetters(name)) { - name = name.substring(0, 2).toLowerCase() + name.substring(2); - } - - // camelize (lower first character) the variable name - // pet_id => petId - name = camelize(name, true); - - // for reserved word or word starting with number, append _ - if (isReservedWord(name) || name.matches("^\\d.*")) { - name = escapeReservedWord(name); - } - - return name; - } - - @Override - public String toParamName(String name) { - // to avoid conflicts with 'callback' parameter for async call - if ("callback".equals(name)) { - return "paramCallback"; - } - - // should be the same as variable name - return toVarName(name); - } - - @Override - public String toModelFilename(String name) { - // should be the same as the model name - return toModelName(name); - } - - @Override - public String getTypeDeclaration(Property p) { - if (p instanceof ArrayProperty) { - ArrayProperty ap = (ArrayProperty) p; - Property inner = ap.getItems(); - if (inner == null) { - LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning null - return null; - } - return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; - } else if (p instanceof MapProperty) { - MapProperty mp = (MapProperty) p; - Property inner = mp.getAdditionalProperties(); - if (inner == null) { - LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning null - return null; - } - return getSwaggerType(p) + ""; - } - return super.getTypeDeclaration(p); - } - - @Override - public String toDefaultValue(Property p) { - if (p instanceof ArrayProperty) { - final ArrayProperty ap = (ArrayProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.ArrayList<%s>()"; - } else { - pattern = "new ArrayList<%s>()"; - } - if (ap.getItems() == null) { - return null; - } - - return String.format(pattern, getTypeDeclaration(ap.getItems())); - } else if (p instanceof MapProperty) { - final MapProperty ap = (MapProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.HashMap<%s>()"; - } else { - pattern = "new HashMap<%s>()"; - } - if (ap.getAdditionalProperties() == null) { - return null; - } - - return String.format(pattern, - String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); - } else if (p instanceof IntegerProperty) { - IntegerProperty dp = (IntegerProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - return "null"; - } else if (p instanceof LongProperty) { - LongProperty dp = (LongProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "l"; - } - return "null"; - } else if (p instanceof DoubleProperty) { - DoubleProperty dp = (DoubleProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "d"; - } - return "null"; - } else if (p instanceof FloatProperty) { - FloatProperty dp = (FloatProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "f"; - } - return "null"; - } else if (p instanceof BooleanProperty) { - BooleanProperty bp = (BooleanProperty) p; - if (bp.getDefault() != null) { - return bp.getDefault().toString(); - } - return "null"; - } else if (p instanceof StringProperty) { - StringProperty sp = (StringProperty) p; - if (sp.getDefault() != null) { - String _default = sp.getDefault(); - if (sp.getEnum() == null) { - return "\"" + escapeText(_default) + "\""; - } else { - // convert to enum var name later in postProcessModels - return _default; - } - } - return "null"; - } - return super.toDefaultValue(p); - } - - @Override - public String toExampleValue(Property p) { - if (p.getExample() != null) { - return escapeText(p.getExample().toString()); - } else { - return super.toExampleValue(p); - } - } - - @Override - public String toOperationId(String operationId) { - // throw exception if method name is empty - if (StringUtils.isEmpty(operationId)) { - throw new RuntimeException("Empty method/operation name (operationId) not allowed"); - } - - operationId = camelize(sanitizeName(operationId), true); - - // method name cannot use reserved keyword, e.g. return - if (isReservedWord(operationId)) { - String newOperationId = camelize("call_" + operationId, true); - LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " - + newOperationId); - return newOperationId; - } - - return operationId; - } - - @Override - protected boolean needToImport(String type) { - return super.needToImport(type) && type.indexOf(".") < 0; - } - - @Override - public String toEnumName(CodegenProperty property) { - return sanitizeName(camelize(property.name)) + "Enum"; - } - - @Override - public String toEnumVarName(String value, String datatype) { - if (value.length() == 0) { - return "EMPTY"; - } - - // for symbol, e.g. $, # - if (getSymbolName(value) != null) { - return getSymbolName(value).toUpperCase(); - } - - // number - if ("Integer".equals(datatype) || "Long".equals(datatype) || - "Float".equals(datatype) || "Double".equals(datatype)) { - String varName = "NUMBER_" + value; - varName = varName.replace("-", "MINUS_"); - varName = varName.replace("\\+", "PLUS_"); - varName = varName.replace("\\.", "_DOT_"); - return varName; - } - - // string - String var = value.replace("\\W+", "_").toUpperCase(); - if (var.matches("\\d.*")) { - return "_" + var; - } else { - return var; - } - } - - @Override - public String toEnumValue(String value, String datatype) { - if ("Integer".equals(datatype) || "Long".equals(datatype) || - "Double".equals(datatype)) { - return value; - } else if ("Float".equals(datatype)) { - // add f to number, e.g. 3.14 => 3.14f - return value + "f"; - } else { - return "\"" + escapeText(value) + "\""; - } - } - - @Override - public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, - Map definitions, Swagger swagger) { - CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); - op.path = sanitizePath(op.path); - return op; - } - - @Override - public String escapeQuotationMark(String input) { - // remove " to avoid code injection - return input.replace("\"", ""); - } - - @Override - public String escapeUnsafeCharacters(String input) { - return input.replace("*/", "*_/").replace("/*", "/_*"); - } - - public boolean convertPropertyToBoolean(String propertyKey) { - boolean booleanValue = false; - if (additionalProperties.containsKey(propertyKey)) { - booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); - } - - return booleanValue; - } - - public String toRegularExpression(String pattern) { - return escapeText(pattern); - } - - @Override - public String sanitizeTag(String tag) { - return camelize(sanitizeName(tag)); - } - - public String toBooleanGetter(String name) { - return "is" + getterAndSetterCapitalize(name); - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getArtifactId() { - return artifactId; - } - - public void setArtifactId(String artifactId) { - this.artifactId = artifactId; - } - - public String getArtifactVersion() { - return artifactVersion; - } - - public void setArtifactVersion(String artifactVersion) { - this.artifactVersion = artifactVersion; - } - - - public String getProjectFolder() { - return projectFolder; - } - - public void setProjectFolder(String projectFolder) { - this.projectFolder = projectFolder; - } - - public String getEurekaUri() { + public static final String FULL_JAVA_UTIL = "fullJavaUtil"; + public static final String SUPPORT_JAVA6 = "supportJava6"; + public static final String CONFIG_PACKAGE = "configPackage"; + public static final String BASE_PACKAGE = "basePackage"; + public static final String TITLE = "title"; + public static final String WITH_XML = "withXml"; + public static final String EUREKA_URI = "eurekaUri"; + public static final String ZIPKIN_URI = "zipkinUri"; + public static final String SPRINGADMIN_URI = "springBootAdminUri"; + protected String groupId = "com.prokarma"; + protected String artifactId = "pkmst-microservice"; + protected String artifactVersion = "1.0.0"; + protected String projectFolder; + + protected String projectTestFolder; + protected String sourceFolder; + protected String testFolder; + protected String basePackage = "com.prokarma.pkmst"; + protected String serviceName = "Pkmst"; + protected String configPackage = "com.prokarma.pkmst.config"; + protected boolean implicitHeaders = false; + protected boolean serializeBigDecimalAsString = false; + protected boolean withXml = false; + protected boolean fullJavaUtil; + protected String javaUtilPrefix = ""; + protected Boolean serializableModel = false; + protected String invokerPackage; + protected String title; + protected String apiDocPath = "docs/"; + protected String modelDocPath = "docs/"; + protected String eurekaUri; + protected String zipkinUri; + protected String springBootAdminUri; + + public PkmstServerCodegen() { + super(); + this.projectFolder = "src" + File.separator + "main"; + this.projectTestFolder = "src" + File.separator + "test"; + this.sourceFolder = this.projectFolder + File.separator + "java"; + this.testFolder = this.projectTestFolder + File.separator + "java"; + embeddedTemplateDir = templateDir = "pkmst"; + apiPackage = "com.prokarma.pkmst.controller"; + modelPackage = "com.prokarma.pkmst.model"; + invokerPackage = "com.prokarma.pkmst.controller"; + setReservedWordsLowerCase(Arrays.asList( + // used as internal variables, can collide with parameter names + "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", "localVarHeaderParams", + "localVarFormParams", "localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes", + "localVarContentType", "localVarAuthNames", "localReturnType", "ApiClient", "ApiException", + "ApiResponse", "Configuration", "StringUtil", + + // language reserved words + "abstract", "continue", "for", "new", "switch", "assert", "default", "if", "package", "synchronized", + "boolean", "do", "goto", "private", "this", "break", "double", "implements", "protected", "throw", + "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", + "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while", "null")); + + this.languageSpecificPrimitives = new HashSet(Arrays.asList("String", "boolean", "Boolean", "Double", + "Integer", "Long", "Float", "Object", "byte[]")); + this.instantiationTypes.put("array", "ArrayList"); + this.instantiationTypes.put("map", "HashMap"); + this.typeMapping.put("date", "Date"); + this.typeMapping.put("file", "File"); + + this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); + this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); + this.cliOptions.add(new CliOption("serviceName", "Service Name")); + this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); + this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); + this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); + this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); + // Middleware config + this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); + this.apiTestTemplateFiles.put("api_test.mustache", ".java"); + this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); + this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); + } + + private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { + // This generator uses inline classes to define enums, which breaks when + // dealing with models that have subTypes. To clean this up, we will analyze + // the parent and child models, look for enums that match, and remove + // them from the child models and leave them in the parent. + // Because the child models extend the parents, the enums will be available via + // the parent. + + // Only bother with reconciliation if the parent model has enums. + if (!parentCodegenModel.hasEnums) { + return codegenModel; + } + + // Get the properties for the parent and child models + final List parentModelCodegenProperties = parentCodegenModel.vars; + List codegenProperties = codegenModel.vars; + + // Iterate over all of the parent model properties + boolean removedChildEnum = false; + for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { + // Look for enums + if (parentModelCodegenPropery.isEnum) { + // Now that we have found an enum in the parent class, + // and search the child class for the same enum. + Iterator iterator = codegenProperties.iterator(); + while (iterator.hasNext()) { + CodegenProperty codegenProperty = iterator.next(); + if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { + // We found an enum in the child class that is + // a duplicate of the one in the parent, so remove it. + iterator.remove(); + removedChildEnum = true; + } + } + } + } + + if (removedChildEnum) { + // If we removed an entry from this model's vars, we need to ensure hasMore is + // updated + int count = 0, numVars = codegenProperties.size(); + for (CodegenProperty codegenProperty : codegenProperties) { + count += 1; + codegenProperty.hasMore = (count < numVars) ? true : false; + } + codegenModel.vars = codegenProperties; + } + return codegenModel; + } + + private static String getAccept(Operation operation) { + String accepts = null; + String defaultContentType = "application/json"; + if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String produces : operation.getProduces()) { + if (defaultContentType.equalsIgnoreCase(produces)) { + accepts = defaultContentType; + break; + } else { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(produces); + } + } + if (accepts == null) { + accepts = sb.toString(); + } + } else { + accepts = defaultContentType; + } + + return accepts; + } + + public CodegenType getTag() { + return CodegenType.SERVER; + } + + public String getName() { + return "pkmst"; + } + + public String getHelp() { + return "Generates a Java SpringBoot Server application using the SpringFox integration." + + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; + } + + public void processOpts() { + super.processOpts(); + if (this.additionalProperties.containsKey("basePackage")) { + this.setBasePackage((String) this.additionalProperties.get("basePackage")); + this.setInvokerPackage(this.getBasePackage()); + this.apiPackage = this.getBasePackage() + ".controller"; + this.modelPackage = this.getBasePackage() + ".model"; + this.setConfigPackage(this.getBasePackage() + ".config"); + + // this.additionalProperties.put(BASE_PACKAGE, this.getBasePackage()); + } else { + this.additionalProperties.put(BASE_PACKAGE, basePackage); + this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); + this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); + this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); + this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + } + if (this.additionalProperties.containsKey("groupId")) { + this.setGroupId((String) this.additionalProperties.get("groupId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.GROUP_ID, groupId); + } + if (this.additionalProperties.containsKey("artifactId")) { + this.setArtifactId((String) this.additionalProperties.get("artifactId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); + } + if (this.additionalProperties.containsKey("artifactVersion")) { + this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + } + if (this.additionalProperties.containsKey("serviceName")) { + this.setServiceName((String) this.additionalProperties.get("serviceName")); + } else { + // not set, use to be passed to template + additionalProperties.put("serviceName", serviceName); + } + + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { + this.setSerializeBigDecimalAsString(Boolean.valueOf( + this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); + } + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { + this.setSerializableModel( + Boolean.valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); + } + if (this.additionalProperties.containsKey(TITLE)) { + this.setTitle((String) this.additionalProperties.get(TITLE)); + } + this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); + if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { + this.setFullJavaUtil(Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); + } + + if (this.additionalProperties.containsKey(EUREKA_URI)) { + this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); + } + if (this.additionalProperties.containsKey(ZIPKIN_URI)) { + this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); + } + if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { + this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); + } + if (fullJavaUtil) { + javaUtilPrefix = "java.util."; + } + this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); + this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); + this.additionalProperties.put(SUPPORT_JAVA6, false); + this.additionalProperties.put("java8", true); + + if (this.additionalProperties.containsKey(WITH_XML)) { + this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); + } + this.additionalProperties.put(WITH_XML, withXml); + + // make api and model doc path available in mustache template + this.additionalProperties.put("apiDocPath", apiDocPath); + this.additionalProperties.put("modelDocPath", modelDocPath); + + this.importMapping.put("List", "java.util.List"); + + if (fullJavaUtil) { + this.typeMapping.put("array", "java.util.List"); + this.typeMapping.put("map", "java.util.Map"); + this.typeMapping.put("DateTime", "java.util.Date"); + this.typeMapping.put("UUID", "java.util.UUID"); + this.typeMapping.remove("List"); + this.importMapping.remove("Date"); + this.importMapping.remove("Map"); + this.importMapping.remove("HashMap"); + this.importMapping.remove("Array"); + this.importMapping.remove("ArrayList"); + this.importMapping.remove("List"); + this.importMapping.remove("Set"); + this.importMapping.remove("DateTime"); + this.importMapping.remove("UUID"); + this.instantiationTypes.put("array", "java.util.ArrayList"); + this.instantiationTypes.put("map", "java.util.HashMap"); + } + // optional jackson mappings for BigDecimal support + this.importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); + this.importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); + + // imports for pojos + this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); + this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); + this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); + this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); + this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); + this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); + this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); + this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); + this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); + this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); + this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); + this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); + this.importMapping.put("IOException", "java.io.IOException"); + this.importMapping.put("Objects", "java.util.Objects"); + this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); + // import JsonCreator if JsonProperty is imported + // used later in recursive import in postProcessingModels + this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", + "com.fasterxml.jackson.annotation.JsonCreator"); + + this.apiTemplateFiles.put("api.mustache", ".java"); + this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); + + this.modelTemplateFiles.put("model.mustache", ".java"); + + this.supportingFiles.add(new SupportingFile("SpringBootApplication.mustache", + (this.getSourceFolder() + File.separator + this.getBasePackage()).replace(".", File.separator), + this.getServiceName() + "Application" + ".java")); + + this.supportingFiles + .add(new SupportingFile("config" + File.separator + "swaggerDocumentationConfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", + java.io.File.separator) + File.separator + "swagger", + "SwaggerDocumentationConfig.java")); + + this.supportingFiles.add(new SupportingFile("config" + File.separator + "pkmstproperties.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator + "swagger", + "PkmstProperties.java")); + this.supportingFiles.add(new SupportingFile("config" + File.separator + "appconfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator, + "AppConfig.java")); + + // Security + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "authorizationServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "AuthorizationServerConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "oAuth2SecurityConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "OAuth2SecurityConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "resourceServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "ResourceServerConfiguration.java")); + + // logging + + this.supportingFiles.add(new SupportingFile("logging" + File.separator + "httpLoggingFilter.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + File.separator + + "logging", + "HttpLoggingFilter.java")); + + // Resources + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-local.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-local.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev-config.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev-config.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "bootstrap.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + + // POM + this.supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + + // Readme + this.supportingFiles.add(new SupportingFile("readme.mustache", "", "Readme.md")); + + // manifest + + this.supportingFiles.add(new SupportingFile("manifest.mustache", "", "manifest.yml")); + + // docker + this.supportingFiles.add(new SupportingFile("docker.mustache", "", "Dockerfile")); + + // logstash + + this.supportingFiles.add(new SupportingFile("logstash.mustache", "", "logstash.conf")); + + // Cucumber + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "executeReport.mustache", + this.testFolder + File.separator + this.basePackage.replace(".", File.separator) + File.separator + + "cucumber" + File.separator + "report", + "ExecuteReport.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberTest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Test.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberSteps.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Steps.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "package.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "package-info.java")); + + // test resources + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "cucumber.mustache", + (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "cucumber", + serviceName + ".feature")); + + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "bootstrap.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.properties")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application-test.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application-test.properties")); + + // Gatling + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "gatling.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "gatling.conf")); + + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.conf")); + + this.supportingFiles.add(new SupportingFile( + "gatling" + File.separator + "testapi.mustache", ("src") + File.separator + ("test") + File.separator + + ("scala") + File.separator + ("scalaFiles").replace(".", java.io.File.separator), + "testapi.scala")); + + /* + * this.supportingFiles.add(new SupportingFile( "gatling" + File.separator + + * "package.mustache", ("src")+ File.separator + ("test")+ File.separator + + * ("scala")+ File.separator + ("scalaFiles").replace(".", + * java.io.File.separator), "package.info")); + */ + + // adding class for integration test + this.supportingFiles.add(new SupportingFile( + "integration" + File.separator + "integrationtest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "controller", + serviceName + "IT.java")); + } + + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (final CodegenOperation operation : ops) { + List responses = operation.responses; + if (responses != null) { + for (final CodegenResponse resp : responses) { + if ("0".equals(resp.code)) { + resp.code = "200"; + } + doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + resp.dataType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + resp.containerType = returnContainer; + } + }); + } + } + + doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + operation.returnType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + operation.returnContainer = returnContainer; + } + }); + + if (implicitHeaders) { + removeHeadersFromAllParams(operation.allParams); + } + } + } + + return objs; + } + + /** + * This method removes header parameters from the list of parameters and also + * corrects last allParams hasMore state. + * + * @param allParams + * list of all parameters + */ + private void removeHeadersFromAllParams(List allParams) { + if (allParams.isEmpty()) { + return; + } + final ArrayList copy = new ArrayList(allParams); + allParams.clear(); + + for (CodegenParameter p : copy) { + if (!p.isHeaderParam) { + allParams.add(p); + } + } + allParams.get(allParams.size() - 1).hasMore = false; + } + + /** + * @param returnType + * The return type that needs to be converted + * @param dataTypeAssigner + * An object that will assign the data to the respective fields in + * the model. + */ + private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { + final String rt = returnType; + if (rt == null) { + dataTypeAssigner.setReturnType("Void"); + } else if (rt.startsWith("List")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("List"); + } + } else if (rt.startsWith("Map")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); + dataTypeAssigner.setReturnContainer("Map"); + } + } else if (rt.startsWith("Set")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("Set"); + } + } + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + + swaggerType = getAlias(swaggerType); + + // don't apply renaming on types from the typeMapping + if (this.typeMapping.containsKey(swaggerType)) { + return this.typeMapping.get(swaggerType); + } + + if (null == swaggerType) { + LOGGER.error("No Type defined for Property " + p); + } + return toModelName(swaggerType); + } + + @Override + public String getAlias(String name) { + if (typeAliases.containsKey(name)) { + return typeAliases.get(name); + } + return name; + } + + @Override + public String toModelName(final String name) { + // We need to check if import-mapping has a different model for this class, so + // we use it + // instead of the auto-generated one. + if (this.importMapping.containsKey(name)) { + return this.importMapping.get(name); + } + + final String sanitizedName = sanitizeName(name); + + String nameWithPrefixSuffix = sanitizedName; + if (!StringUtils.isEmpty(modelNamePrefix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; + } + + if (!StringUtils.isEmpty(modelNameSuffix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; + } + + // camelize the model name + // phone_number => PhoneNumber + final String camelizedName = camelize(nameWithPrefixSuffix); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(camelizedName)) { + final String modelName = "Model" + camelizedName; + LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); + return modelName; + } + + // model name starts with number + if (camelizedName.matches("^\\d.*")) { + final String modelName = "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize) + LOGGER.warn( + name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName); + return modelName; + } + + return camelizedName; + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + if (serializeBigDecimalAsString) { + if (property.baseType.equals("BigDecimal")) { + // we serialize BigDecimal as `string` to avoid precision loss + property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); + + // this requires some more imports to be added for this model... + model.imports.add("ToStringSerializer"); + model.imports.add("JsonSerialize"); + } + } + + if (!fullJavaUtil) { + if ("array".equals(property.containerType)) { + model.imports.add("ArrayList"); + } else if ("map".equals(property.containerType)) { + model.imports.add("HashMap"); + } + } + + if (!BooleanUtils.toBoolean(model.isEnum)) { + // needed by all pojos, but not enums + model.imports.add("ApiModelProperty"); + model.imports.add("ApiModel"); + } + + // super.postProcessModelProperty(model, property); + + if ("null".equals(property.example)) { + property.example = null; + } + + // Add imports for Jackson + if (!Boolean.TRUE.equals(model.isEnum)) { + model.imports.add("JsonProperty"); + + if (Boolean.TRUE.equals(model.hasEnums)) { + model.imports.add("JsonValue"); + } + } else { // enum class + // Needed imports for Jackson's JsonCreator + if (this.additionalProperties.containsKey("jackson")) { + model.imports.add("JsonCreator"); + } + } + } + + @Override + public Map postProcessModelsEnum(Map objs) { + objs = super.postProcessModelsEnum(objs); + + // Add imports for Jackson + List> imports = (List>) objs.get("imports"); + List models = (List) objs.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + // for enum model + if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { + cm.imports.add(this.importMapping.get("JsonValue")); + Map item = new HashMap(); + item.put("import", this.importMapping.get("JsonValue")); + imports.add(item); + } + } + + return objs; + } + + @Override + public CodegenModel fromModel(String name, Model model, Map allDefinitions) { + CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); + if (codegenModel.description != null) { + codegenModel.imports.add("ApiModel"); + } + if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { + codegenModel.imports.add("JsonSubTypes"); + codegenModel.imports.add("JsonTypeInfo"); + } + if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { + final Model parentModel = allDefinitions.get(codegenModel.parentSchema); + final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); + codegenModel = PkmstServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); + } + return codegenModel; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + return objs; + } + + @Override + public Map postProcessModels(Map objs) { + // recursively add import for mapping one type to multiple imports + List> recursiveImports = (List>) objs.get("imports"); + if (recursiveImports == null) { + return objs; + } + + ListIterator> listIterator = recursiveImports.listIterator(); + while (listIterator.hasNext()) { + String _import = listIterator.next().get("import"); + // if the import package happens to be found in the importMapping (key) + // add the corresponding import package to the list + if (importMapping.containsKey(_import)) { + Map newImportMap = new HashMap(); + newImportMap.put("import", importMapping.get(_import)); + listIterator.add(newImportMap); + } + } + + return postProcessModelsEnum(objs); + } + + @Override + public void preprocessSwagger(Swagger swagger) { + super.preprocessSwagger(swagger); + if (swagger == null || swagger.getPaths() == null) { + return; + } + if (swagger.getTags() != null) { + System.out.println("Tags are::" + swagger.getTags()); + List resourcePaths = new ArrayList(); + for (Tag tag : swagger.getTags()) { + ResourcePath resourcePath = new ResourcePath(); + resourcePath.setPath(tag.getName()); + resourcePaths.add(resourcePath); + } + this.additionalProperties.put("resourcePaths", resourcePaths); + } + // get vendor extensions + + Map vendorExt = swagger.getInfo().getVendorExtensions(); + if (vendorExt != null && !vendorExt.toString().equals("")) { + if (vendorExt.containsKey("x-codegen")) { + + Map uris = (Map) vendorExt.get("x-codegen"); + if (uris.containsKey("eurekaUri")) { + String eurekaUri = uris.get("eurekaUri"); + additionalProperties.put(EUREKA_URI, eurekaUri); + } + if (uris.containsKey("zipkinUri")) { + String zipkinUri = uris.get("zipkinUri"); + additionalProperties.put(ZIPKIN_URI, zipkinUri); + } + if (uris.containsKey("springBootAdminUri")) { + String springBootAdminUri = uris.get("springBootAdminUri"); + additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); + } + if (uris.containsKey("pkmstInterceptor")) { + String pkmstInterceptor = uris.get("pkmstInterceptor"); + additionalProperties.put("pkmstInterceptor", pkmstInterceptor); + } + } + } + + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() == null) { + continue; + } + for (Operation operation : path.getOperations()) { + boolean hasFormParameters = false; + for (Parameter parameter : operation.getParameters()) { + if (parameter instanceof FormParameter) { + hasFormParameters = true; + } + } + // only add content-Type if its no a GET-Method + if (path.getGet() != null || !operation.equals(path.getGet())) { + String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" + : "application/json"; + String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() + ? defaultContentType + : operation.getConsumes().get(0); + operation.setVendorExtension("x-contentType", contentType); + } + String accepts = getAccept(operation); + operation.setVendorExtension("x-accepts", accepts); + } + } + + if ("/".equals(swagger.getBasePath())) { + swagger.setBasePath(""); + } + + if (!additionalProperties.containsKey(TITLE)) { + // From the title, compute a reasonable name for the package and the API + String title = swagger.getInfo().getTitle(); + + // Drop any API suffix + if (title != null) { + title = title.trim().replace(" ", "-"); + if (title.toUpperCase().endsWith("API")) { + title = title.substring(0, title.length() - 3); + } + + this.title = camelize(sanitizeName(title), true); + } + additionalProperties.put(TITLE, this.title); + } + + String host = swagger.getHost(); + String port = "8008"; + if (host != null) { + String[] parts = host.split(":"); + if (parts.length > 1) { + port = parts[1]; + } + } + + this.additionalProperties.put("serverPort", port); + if (swagger.getPaths() != null) { + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() != null) { + for (Operation operation : path.getOperations()) { + if (operation.getTags() != null) { + List> tags = new ArrayList>(); + for (String tag : operation.getTags()) { + Map value = new HashMap(); + value.put("tag", tag); + value.put("hasMore", "true"); + tags.add(value); + } + if (tags.size() > 0) { + tags.get(tags.size() - 1).remove("hasMore"); + } + if (operation.getTags().size() > 0) { + String tag = operation.getTags().get(0); + operation.setTags(Arrays.asList(tag)); + } + operation.setVendorExtension("x-tags", tags); + } + } + } + } + } + } + + @Override + public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, + Map> operations) { + String basePath = resourcePath; + if (basePath.startsWith("/")) { + basePath = basePath.substring(1); + } + int pos = basePath.indexOf("/"); + if (pos > 0) { + basePath = basePath.substring(0, pos); + } + + if (basePath.equals("")) { + basePath = "default"; + } else { + co.subresourceOperation = !co.path.isEmpty(); + } + List opList = operations.get(basePath); + if (opList == null) { + opList = new ArrayList(); + operations.put(basePath, opList); + } + opList.add(co); + co.baseName = basePath; + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultApi"; + } + name = sanitizeName(name); + return camelize(name) + "Api"; + } + + @Override + public void setParameterExampleValue(CodegenParameter p) { + String type = p.baseType; + if (type == null) { + type = p.dataType; + } + + if ("File".equals(type)) { + String example; + + if (p.defaultValue == null) { + example = p.example; + } else { + example = p.defaultValue; + } + + if (example == null) { + example = "/path/to/file"; + } + example = "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText(example) + + "\"))"; + p.example = example; + } else { + super.setParameterExampleValue(p); + } + } + + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; + } + + @Override + public String apiFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String apiTestFileFolder() { + return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String modelFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); + } + + @Override + public String apiDocFileFolder() { + return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); + } + + @Override + public String modelDocFileFolder() { + return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods + // parameters as 'final'. + + if (name.toLowerCase().matches("^_*class$")) { + return "propertyClass"; + } + + if ("_".equals(name)) { + name = "_u"; + } + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + if (startsWithTwoUppercaseLetters(name)) { + name = name.substring(0, 2).toLowerCase() + name.substring(2); + } + + // camelize (lower first character) the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved word or word starting with number, append _ + if (isReservedWord(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public String toParamName(String name) { + // to avoid conflicts with 'callback' parameter for async call + if ("callback".equals(name)) { + return "paramCallback"; + } + + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + if (inner == null) { + LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning null + return null; + } + return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + if (inner == null) { + LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning null + return null; + } + return getSwaggerType(p) + ""; + } + return super.getTypeDeclaration(p); + } + + @Override + public String toDefaultValue(Property p) { + if (p instanceof ArrayProperty) { + final ArrayProperty ap = (ArrayProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.ArrayList<%s>()"; + } else { + pattern = "new ArrayList<%s>()"; + } + if (ap.getItems() == null) { + return null; + } + + return String.format(pattern, getTypeDeclaration(ap.getItems())); + } else if (p instanceof MapProperty) { + final MapProperty ap = (MapProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.HashMap<%s>()"; + } else { + pattern = "new HashMap<%s>()"; + } + if (ap.getAdditionalProperties() == null) { + return null; + } + + return String.format(pattern, + String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); + } else if (p instanceof IntegerProperty) { + IntegerProperty dp = (IntegerProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + return "null"; + } else if (p instanceof LongProperty) { + LongProperty dp = (LongProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "l"; + } + return "null"; + } else if (p instanceof DoubleProperty) { + DoubleProperty dp = (DoubleProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "d"; + } + return "null"; + } else if (p instanceof FloatProperty) { + FloatProperty dp = (FloatProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "f"; + } + return "null"; + } else if (p instanceof BooleanProperty) { + BooleanProperty bp = (BooleanProperty) p; + if (bp.getDefault() != null) { + return bp.getDefault().toString(); + } + return "null"; + } else if (p instanceof StringProperty) { + StringProperty sp = (StringProperty) p; + if (sp.getDefault() != null) { + String _default = sp.getDefault(); + if (sp.getEnum() == null) { + return "\"" + escapeText(_default) + "\""; + } else { + // convert to enum var name later in postProcessModels + return _default; + } + } + return "null"; + } + return super.toDefaultValue(p); + } + + @Override + public String toExampleValue(Property p) { + if (p.getExample() != null) { + return escapeText(p.getExample().toString()); + } else { + return super.toExampleValue(p); + } + } + + @Override + public String toOperationId(String operationId) { + // throw exception if method name is empty + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method/operation name (operationId) not allowed"); + } + + operationId = camelize(sanitizeName(operationId), true); + + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + String newOperationId = camelize("call_" + operationId, true); + LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); + return newOperationId; + } + + return operationId; + } + + @Override + protected boolean needToImport(String type) { + return super.needToImport(type) && type.indexOf(".") < 0; + } + + @Override + public String toEnumName(CodegenProperty property) { + return sanitizeName(camelize(property.name)) + "Enum"; + } + + @Override + public String toEnumVarName(String value, String datatype) { + if (value.length() == 0) { + return "EMPTY"; + } + + // for symbol, e.g. $, # + if (getSymbolName(value) != null) { + return getSymbolName(value).toUpperCase(); + } + + // number + if ("Integer".equals(datatype) || "Long".equals(datatype) || "Float".equals(datatype) + || "Double".equals(datatype)) { + String varName = "NUMBER_" + value; + varName = varName.replace("-", "MINUS_"); + varName = varName.replace("\\+", "PLUS_"); + varName = varName.replace("\\.", "_DOT_"); + return varName; + } + + // string + String var = value.replace("\\W+", "_").toUpperCase(); + if (var.matches("\\d.*")) { + return "_" + var; + } else { + return var; + } + } + + @Override + public String toEnumValue(String value, String datatype) { + if ("Integer".equals(datatype) || "Long".equals(datatype) || "Double".equals(datatype)) { + return value; + } else if ("Float".equals(datatype)) { + // add f to number, e.g. 3.14 => 3.14f + return value + "f"; + } else { + return "\"" + escapeText(value) + "\""; + } + } + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, + Map definitions, Swagger swagger) { + CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); + op.path = sanitizePath(op.path); + return op; + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + public boolean convertPropertyToBoolean(String propertyKey) { + boolean booleanValue = false; + if (additionalProperties.containsKey(propertyKey)) { + booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); + } + + return booleanValue; + } + + public String toRegularExpression(String pattern) { + return escapeText(pattern); + } + + @Override + public String sanitizeTag(String tag) { + return camelize(sanitizeName(tag)); + } + + public String toBooleanGetter(String name) { + return "is" + getterAndSetterCapitalize(name); + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getArtifactVersion() { + return artifactVersion; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public String getProjectFolder() { + return projectFolder; + } + + public void setProjectFolder(String projectFolder) { + this.projectFolder = projectFolder; + } + + public String getEurekaUri() { return eurekaUri; } @@ -1394,146 +1312,146 @@ public String getSpringBootAdminUri() { public void setSpringBootAdminUri(String springBootAdminUri) { this.springBootAdminUri = springBootAdminUri; } - public String getProjectTestFolder() { - return projectTestFolder; - } - public void setProjectTestFolder(String projectTestFolder) { - this.projectTestFolder = projectTestFolder; - } + public String getProjectTestFolder() { + return projectTestFolder; + } - public String getSourceFolder() { - return sourceFolder; - } - - public void setSourceFolder(String sourceFolder) { - this.sourceFolder = sourceFolder; - } - - public String getTestFolder() { - return testFolder; - } + public void setProjectTestFolder(String projectTestFolder) { + this.projectTestFolder = projectTestFolder; + } - public void setTestFolder(String testFolder) { - this.testFolder = testFolder; - } + public String getSourceFolder() { + return sourceFolder; + } - public String getBasePackage() { - return basePackage; - } + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - } + public String getTestFolder() { + return testFolder; + } - public String getServiceName() { - return serviceName; - } + public void setTestFolder(String testFolder) { + this.testFolder = testFolder; + } - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } + public String getBasePackage() { + return basePackage; + } - public String getConfigPackage() { - return configPackage; - } + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } - public void setConfigPackage(String configPackage) { - this.configPackage = configPackage; - } + public String getServiceName() { + return serviceName; + } - public boolean isImplicitHeaders() { - return implicitHeaders; - } + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } - public void setImplicitHeaders(boolean implicitHeaders) { - this.implicitHeaders = implicitHeaders; - } + public String getConfigPackage() { + return configPackage; + } - public boolean isSerializeBigDecimalAsString() { - return serializeBigDecimalAsString; - } + public void setConfigPackage(String configPackage) { + this.configPackage = configPackage; + } - public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { - this.serializeBigDecimalAsString = serializeBigDecimalAsString; - } + public boolean isImplicitHeaders() { + return implicitHeaders; + } - public boolean isFullJavaUtil() { - return fullJavaUtil; - } + public void setImplicitHeaders(boolean implicitHeaders) { + this.implicitHeaders = implicitHeaders; + } - public void setFullJavaUtil(boolean fullJavaUtil) { - this.fullJavaUtil = fullJavaUtil; - } + public boolean isSerializeBigDecimalAsString() { + return serializeBigDecimalAsString; + } - public Boolean getSerializableModel() { - return serializableModel; - } + public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { + this.serializeBigDecimalAsString = serializeBigDecimalAsString; + } - public void setSerializableModel(Boolean serializableModel) { - this.serializableModel = serializableModel; - } + public boolean isFullJavaUtil() { + return fullJavaUtil; + } - public String getInvokerPackage() { - return invokerPackage; - } + public void setFullJavaUtil(boolean fullJavaUtil) { + this.fullJavaUtil = fullJavaUtil; + } - public void setInvokerPackage(String invokerPackage) { - this.invokerPackage = invokerPackage; - } + public Boolean getSerializableModel() { + return serializableModel; + } - public String getTitle() { - return title; - } + public void setSerializableModel(Boolean serializableModel) { + this.serializableModel = serializableModel; + } - public void setTitle(String title) { - this.title = title; - } + public String getInvokerPackage() { + return invokerPackage; + } - public boolean isWithXml() { - return withXml; - } + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } - public void setWithXml(boolean withXml) { - this.withXml = withXml; - } + public String getTitle() { + return title; + } - private boolean startsWithTwoUppercaseLetters(String name) { - boolean startsWithTwoUppercaseLetters = false; - if (name.length() > 1) { - startsWithTwoUppercaseLetters = name.substring(0, 2) - .equals(name.substring(0, 2).toUpperCase()); - } - return startsWithTwoUppercaseLetters; - } + public void setTitle(String title) { + this.title = title; + } - private String sanitizePath(String p) { - //prefer replace a ", instead of a fuLL URL encode for readability - return p.replace("\"", "%22"); - } + public boolean isWithXml() { + return withXml; + } - private interface DataTypeAssigner { + public void setWithXml(boolean withXml) { + this.withXml = withXml; + } - void setReturnType(String returnType); + private boolean startsWithTwoUppercaseLetters(String name) { + boolean startsWithTwoUppercaseLetters = false; + if (name.length() > 1) { + startsWithTwoUppercaseLetters = name.substring(0, 2).equals(name.substring(0, 2).toUpperCase()); + } + return startsWithTwoUppercaseLetters; + } - void setReturnContainer(String returnContainer); - } + private String sanitizePath(String p) { + // prefer replace a ", instead of a fuLL URL encode for readability + return p.replace("\"", "%22"); + } - private class ResourcePath { + private interface DataTypeAssigner { - private String path; + void setReturnType(String returnType); - public String getPath() { - return path; - } + void setReturnContainer(String returnContainer); + } - public void setPath(String path) { - this.path = path; - } + private class ResourcePath { - @Override - public String toString() { - return this.path; - } - } + private String path; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + @Override + public String toString() { + return this.path; + } + } } From e653796113a8fe6e1971fb474bb26c5fc990aa97 Mon Sep 17 00:00:00 2001 From: rkumar-pk Date: Wed, 22 Nov 2017 17:36:21 +0530 Subject: [PATCH 03/19] replaces tab with blank spaces --- .../codegen/languages/PkmstServerCodegen.java | 2756 ++++++++--------- 1 file changed, 1378 insertions(+), 1378 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java index 59b91e14de6..286989028ef 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java @@ -46,1412 +46,1412 @@ */ public class PkmstServerCodegen extends DefaultCodegen implements CodegenConfig { - public static final String FULL_JAVA_UTIL = "fullJavaUtil"; - public static final String SUPPORT_JAVA6 = "supportJava6"; - public static final String CONFIG_PACKAGE = "configPackage"; - public static final String BASE_PACKAGE = "basePackage"; - public static final String TITLE = "title"; - public static final String WITH_XML = "withXml"; - public static final String EUREKA_URI = "eurekaUri"; - public static final String ZIPKIN_URI = "zipkinUri"; - public static final String SPRINGADMIN_URI = "springBootAdminUri"; - protected String groupId = "com.prokarma"; - protected String artifactId = "pkmst-microservice"; - protected String artifactVersion = "1.0.0"; - protected String projectFolder; - - protected String projectTestFolder; - protected String sourceFolder; - protected String testFolder; - protected String basePackage = "com.prokarma.pkmst"; - protected String serviceName = "Pkmst"; - protected String configPackage = "com.prokarma.pkmst.config"; - protected boolean implicitHeaders = false; - protected boolean serializeBigDecimalAsString = false; - protected boolean withXml = false; - protected boolean fullJavaUtil; - protected String javaUtilPrefix = ""; - protected Boolean serializableModel = false; - protected String invokerPackage; - protected String title; - protected String apiDocPath = "docs/"; - protected String modelDocPath = "docs/"; - protected String eurekaUri; - protected String zipkinUri; - protected String springBootAdminUri; - - public PkmstServerCodegen() { - super(); - this.projectFolder = "src" + File.separator + "main"; - this.projectTestFolder = "src" + File.separator + "test"; - this.sourceFolder = this.projectFolder + File.separator + "java"; - this.testFolder = this.projectTestFolder + File.separator + "java"; - embeddedTemplateDir = templateDir = "pkmst"; - apiPackage = "com.prokarma.pkmst.controller"; - modelPackage = "com.prokarma.pkmst.model"; - invokerPackage = "com.prokarma.pkmst.controller"; - setReservedWordsLowerCase(Arrays.asList( - // used as internal variables, can collide with parameter names - "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", "localVarHeaderParams", - "localVarFormParams", "localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes", - "localVarContentType", "localVarAuthNames", "localReturnType", "ApiClient", "ApiException", - "ApiResponse", "Configuration", "StringUtil", - - // language reserved words - "abstract", "continue", "for", "new", "switch", "assert", "default", "if", "package", "synchronized", - "boolean", "do", "goto", "private", "this", "break", "double", "implements", "protected", "throw", - "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", - "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", - "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while", "null")); - - this.languageSpecificPrimitives = new HashSet(Arrays.asList("String", "boolean", "Boolean", "Double", - "Integer", "Long", "Float", "Object", "byte[]")); - this.instantiationTypes.put("array", "ArrayList"); - this.instantiationTypes.put("map", "HashMap"); - this.typeMapping.put("date", "Date"); - this.typeMapping.put("file", "File"); - - this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); - this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); - this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); - this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); - this.cliOptions.add(new CliOption("serviceName", "Service Name")); - this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); - this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); - this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); - this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); - // Middleware config - this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); - this.apiTestTemplateFiles.put("api_test.mustache", ".java"); - this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); - this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); - } - - private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { - // This generator uses inline classes to define enums, which breaks when - // dealing with models that have subTypes. To clean this up, we will analyze - // the parent and child models, look for enums that match, and remove - // them from the child models and leave them in the parent. - // Because the child models extend the parents, the enums will be available via - // the parent. - - // Only bother with reconciliation if the parent model has enums. - if (!parentCodegenModel.hasEnums) { - return codegenModel; - } - - // Get the properties for the parent and child models - final List parentModelCodegenProperties = parentCodegenModel.vars; - List codegenProperties = codegenModel.vars; - - // Iterate over all of the parent model properties - boolean removedChildEnum = false; - for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { - // Look for enums - if (parentModelCodegenPropery.isEnum) { - // Now that we have found an enum in the parent class, - // and search the child class for the same enum. - Iterator iterator = codegenProperties.iterator(); - while (iterator.hasNext()) { - CodegenProperty codegenProperty = iterator.next(); - if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { - // We found an enum in the child class that is - // a duplicate of the one in the parent, so remove it. - iterator.remove(); - removedChildEnum = true; - } - } - } - } - - if (removedChildEnum) { - // If we removed an entry from this model's vars, we need to ensure hasMore is - // updated - int count = 0, numVars = codegenProperties.size(); - for (CodegenProperty codegenProperty : codegenProperties) { - count += 1; - codegenProperty.hasMore = (count < numVars) ? true : false; - } - codegenModel.vars = codegenProperties; - } - return codegenModel; - } - - private static String getAccept(Operation operation) { - String accepts = null; - String defaultContentType = "application/json"; - if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (String produces : operation.getProduces()) { - if (defaultContentType.equalsIgnoreCase(produces)) { - accepts = defaultContentType; - break; - } else { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(produces); - } - } - if (accepts == null) { - accepts = sb.toString(); - } - } else { - accepts = defaultContentType; - } - - return accepts; - } - - public CodegenType getTag() { - return CodegenType.SERVER; - } - - public String getName() { - return "pkmst"; - } - - public String getHelp() { - return "Generates a Java SpringBoot Server application using the SpringFox integration." - + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; - } - - public void processOpts() { - super.processOpts(); - if (this.additionalProperties.containsKey("basePackage")) { - this.setBasePackage((String) this.additionalProperties.get("basePackage")); - this.setInvokerPackage(this.getBasePackage()); - this.apiPackage = this.getBasePackage() + ".controller"; - this.modelPackage = this.getBasePackage() + ".model"; - this.setConfigPackage(this.getBasePackage() + ".config"); - - // this.additionalProperties.put(BASE_PACKAGE, this.getBasePackage()); - } else { - this.additionalProperties.put(BASE_PACKAGE, basePackage); - this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); - this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); - this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); - this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); - } - if (this.additionalProperties.containsKey("groupId")) { - this.setGroupId((String) this.additionalProperties.get("groupId")); - } else { - // not set, use to be passed to template - additionalProperties.put(CodegenConstants.GROUP_ID, groupId); - } - if (this.additionalProperties.containsKey("artifactId")) { - this.setArtifactId((String) this.additionalProperties.get("artifactId")); - } else { - // not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); - } - if (this.additionalProperties.containsKey("artifactVersion")) { - this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); - } else { - // not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); - } - if (this.additionalProperties.containsKey("serviceName")) { - this.setServiceName((String) this.additionalProperties.get("serviceName")); - } else { - // not set, use to be passed to template - additionalProperties.put("serviceName", serviceName); - } - - if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { - this.setSerializeBigDecimalAsString(Boolean.valueOf( - this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); - } - if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { - this.setSerializableModel( - Boolean.valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); - } - if (this.additionalProperties.containsKey(TITLE)) { - this.setTitle((String) this.additionalProperties.get(TITLE)); - } - this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); - if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { - this.setFullJavaUtil(Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); - } - - if (this.additionalProperties.containsKey(EUREKA_URI)) { - this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); - } - if (this.additionalProperties.containsKey(ZIPKIN_URI)) { - this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); - } - if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { - this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); - } - if (fullJavaUtil) { - javaUtilPrefix = "java.util."; - } - this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); - this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); - this.additionalProperties.put(SUPPORT_JAVA6, false); - this.additionalProperties.put("java8", true); - - if (this.additionalProperties.containsKey(WITH_XML)) { - this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); - } - this.additionalProperties.put(WITH_XML, withXml); - - // make api and model doc path available in mustache template - this.additionalProperties.put("apiDocPath", apiDocPath); - this.additionalProperties.put("modelDocPath", modelDocPath); - - this.importMapping.put("List", "java.util.List"); - - if (fullJavaUtil) { - this.typeMapping.put("array", "java.util.List"); - this.typeMapping.put("map", "java.util.Map"); - this.typeMapping.put("DateTime", "java.util.Date"); - this.typeMapping.put("UUID", "java.util.UUID"); - this.typeMapping.remove("List"); - this.importMapping.remove("Date"); - this.importMapping.remove("Map"); - this.importMapping.remove("HashMap"); - this.importMapping.remove("Array"); - this.importMapping.remove("ArrayList"); - this.importMapping.remove("List"); - this.importMapping.remove("Set"); - this.importMapping.remove("DateTime"); - this.importMapping.remove("UUID"); - this.instantiationTypes.put("array", "java.util.ArrayList"); - this.instantiationTypes.put("map", "java.util.HashMap"); - } - // optional jackson mappings for BigDecimal support - this.importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); - this.importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); - - // imports for pojos - this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); - this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); - this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); - this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); - this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); - this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); - this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); - this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); - this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); - this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); - this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); - this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); - this.importMapping.put("IOException", "java.io.IOException"); - this.importMapping.put("Objects", "java.util.Objects"); - this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); - // import JsonCreator if JsonProperty is imported - // used later in recursive import in postProcessingModels - this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", - "com.fasterxml.jackson.annotation.JsonCreator"); - - this.apiTemplateFiles.put("api.mustache", ".java"); - this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); - - this.modelTemplateFiles.put("model.mustache", ".java"); - - this.supportingFiles.add(new SupportingFile("SpringBootApplication.mustache", - (this.getSourceFolder() + File.separator + this.getBasePackage()).replace(".", File.separator), - this.getServiceName() + "Application" + ".java")); - - this.supportingFiles - .add(new SupportingFile("config" + File.separator + "swaggerDocumentationConfig.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", - java.io.File.separator) + File.separator + "swagger", - "SwaggerDocumentationConfig.java")); - - this.supportingFiles.add(new SupportingFile("config" + File.separator + "pkmstproperties.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) - + File.separator + "swagger", - "PkmstProperties.java")); - this.supportingFiles.add(new SupportingFile("config" + File.separator + "appconfig.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) - + File.separator, - "AppConfig.java")); - - // Security - this.supportingFiles - .add(new SupportingFile("security" + File.separator + "authorizationServerConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "AuthorizationServerConfiguration.java")); - this.supportingFiles - .add(new SupportingFile("security" + File.separator + "oAuth2SecurityConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "OAuth2SecurityConfiguration.java")); - this.supportingFiles - .add(new SupportingFile("security" + File.separator + "resourceServerConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "ResourceServerConfiguration.java")); - - // logging - - this.supportingFiles.add(new SupportingFile("logging" + File.separator + "httpLoggingFilter.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + File.separator - + "logging", - "HttpLoggingFilter.java")); - - // Resources - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-local.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "application-local.yml")); - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "application-dev.yml")); - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev-config.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "application-dev-config.yml")); - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "bootstrap.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "bootstrap.yml")); - - // POM - this.supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); - - // Readme - this.supportingFiles.add(new SupportingFile("readme.mustache", "", "Readme.md")); - - // manifest - - this.supportingFiles.add(new SupportingFile("manifest.mustache", "", "manifest.yml")); - - // docker - this.supportingFiles.add(new SupportingFile("docker.mustache", "", "Dockerfile")); - - // logstash - - this.supportingFiles.add(new SupportingFile("logstash.mustache", "", "logstash.conf")); - - // Cucumber - this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "executeReport.mustache", - this.testFolder + File.separator + this.basePackage.replace(".", File.separator) + File.separator - + "cucumber" + File.separator + "report", - "ExecuteReport.java")); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "cucumberTest.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", - serviceName + "Test.java")); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "cucumberSteps.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", - serviceName + "Steps.java")); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "package.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", - serviceName + "package-info.java")); - - // test resources - this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "cucumber.mustache", - (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "cucumber", - serviceName + ".feature")); - - this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "bootstrap.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "bootstrap.yml")); - this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "application.properties")); - this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application-test.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "application-test.properties")); - - // Gatling - this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "gatling.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "gatling.conf")); - - this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "application.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "application.conf")); - - this.supportingFiles.add(new SupportingFile( - "gatling" + File.separator + "testapi.mustache", ("src") + File.separator + ("test") + File.separator - + ("scala") + File.separator + ("scalaFiles").replace(".", java.io.File.separator), - "testapi.scala")); - - /* - * this.supportingFiles.add(new SupportingFile( "gatling" + File.separator + - * "package.mustache", ("src")+ File.separator + ("test")+ File.separator + - * ("scala")+ File.separator + ("scalaFiles").replace(".", - * java.io.File.separator), "package.info")); - */ - - // adding class for integration test - this.supportingFiles.add(new SupportingFile( - "integration" + File.separator + "integrationtest.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "controller", - serviceName + "IT.java")); - } - - @Override - public Map postProcessOperations(Map objs) { - Map operations = (Map) objs.get("operations"); - if (operations != null) { - List ops = (List) operations.get("operation"); - for (final CodegenOperation operation : ops) { - List responses = operation.responses; - if (responses != null) { - for (final CodegenResponse resp : responses) { - if ("0".equals(resp.code)) { - resp.code = "200"; - } - doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { - - public void setReturnType(final String returnType) { - resp.dataType = returnType; - } - - public void setReturnContainer(final String returnContainer) { - resp.containerType = returnContainer; - } - }); - } - } - - doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { - - public void setReturnType(final String returnType) { - operation.returnType = returnType; - } - - public void setReturnContainer(final String returnContainer) { - operation.returnContainer = returnContainer; - } - }); - - if (implicitHeaders) { - removeHeadersFromAllParams(operation.allParams); - } - } - } - - return objs; - } - - /** - * This method removes header parameters from the list of parameters and also - * corrects last allParams hasMore state. - * - * @param allParams - * list of all parameters - */ - private void removeHeadersFromAllParams(List allParams) { - if (allParams.isEmpty()) { - return; - } - final ArrayList copy = new ArrayList(allParams); - allParams.clear(); - - for (CodegenParameter p : copy) { - if (!p.isHeaderParam) { - allParams.add(p); - } - } - allParams.get(allParams.size() - 1).hasMore = false; - } - - /** - * @param returnType - * The return type that needs to be converted - * @param dataTypeAssigner - * An object that will assign the data to the respective fields in - * the model. - */ - private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { - final String rt = returnType; - if (rt == null) { - dataTypeAssigner.setReturnType("Void"); - } else if (rt.startsWith("List")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); - dataTypeAssigner.setReturnContainer("List"); - } - } else if (rt.startsWith("Map")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); - dataTypeAssigner.setReturnContainer("Map"); - } - } else if (rt.startsWith("Set")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); - dataTypeAssigner.setReturnContainer("Set"); - } - } - } - - @Override - public String getSwaggerType(Property p) { - String swaggerType = super.getSwaggerType(p); - - swaggerType = getAlias(swaggerType); - - // don't apply renaming on types from the typeMapping - if (this.typeMapping.containsKey(swaggerType)) { - return this.typeMapping.get(swaggerType); - } - - if (null == swaggerType) { - LOGGER.error("No Type defined for Property " + p); - } - return toModelName(swaggerType); - } - - @Override - public String getAlias(String name) { - if (typeAliases.containsKey(name)) { - return typeAliases.get(name); - } - return name; - } - - @Override - public String toModelName(final String name) { - // We need to check if import-mapping has a different model for this class, so - // we use it - // instead of the auto-generated one. - if (this.importMapping.containsKey(name)) { - return this.importMapping.get(name); - } - - final String sanitizedName = sanitizeName(name); - - String nameWithPrefixSuffix = sanitizedName; - if (!StringUtils.isEmpty(modelNamePrefix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; - } - - if (!StringUtils.isEmpty(modelNameSuffix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; - } - - // camelize the model name - // phone_number => PhoneNumber - final String camelizedName = camelize(nameWithPrefixSuffix); - - // model name cannot use reserved keyword, e.g. return - if (isReservedWord(camelizedName)) { - final String modelName = "Model" + camelizedName; - LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); - return modelName; - } - - // model name starts with number - if (camelizedName.matches("^\\d.*")) { - final String modelName = "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize) - LOGGER.warn( - name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName); - return modelName; - } - - return camelizedName; - } - - @Override - public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - if (serializeBigDecimalAsString) { - if (property.baseType.equals("BigDecimal")) { - // we serialize BigDecimal as `string` to avoid precision loss - property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); - - // this requires some more imports to be added for this model... - model.imports.add("ToStringSerializer"); - model.imports.add("JsonSerialize"); - } - } - - if (!fullJavaUtil) { - if ("array".equals(property.containerType)) { - model.imports.add("ArrayList"); - } else if ("map".equals(property.containerType)) { - model.imports.add("HashMap"); - } - } - - if (!BooleanUtils.toBoolean(model.isEnum)) { - // needed by all pojos, but not enums - model.imports.add("ApiModelProperty"); - model.imports.add("ApiModel"); - } - - // super.postProcessModelProperty(model, property); - - if ("null".equals(property.example)) { - property.example = null; - } - - // Add imports for Jackson - if (!Boolean.TRUE.equals(model.isEnum)) { - model.imports.add("JsonProperty"); - - if (Boolean.TRUE.equals(model.hasEnums)) { - model.imports.add("JsonValue"); - } - } else { // enum class - // Needed imports for Jackson's JsonCreator - if (this.additionalProperties.containsKey("jackson")) { - model.imports.add("JsonCreator"); - } - } - } - - @Override - public Map postProcessModelsEnum(Map objs) { - objs = super.postProcessModelsEnum(objs); - - // Add imports for Jackson - List> imports = (List>) objs.get("imports"); - List models = (List) objs.get("models"); - for (Object _mo : models) { - Map mo = (Map) _mo; - CodegenModel cm = (CodegenModel) mo.get("model"); - // for enum model - if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { - cm.imports.add(this.importMapping.get("JsonValue")); - Map item = new HashMap(); - item.put("import", this.importMapping.get("JsonValue")); - imports.add(item); - } - } - - return objs; - } - - @Override - public CodegenModel fromModel(String name, Model model, Map allDefinitions) { - CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); - if (codegenModel.description != null) { - codegenModel.imports.add("ApiModel"); - } - if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { - codegenModel.imports.add("JsonSubTypes"); - codegenModel.imports.add("JsonTypeInfo"); - } - if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { - final Model parentModel = allDefinitions.get(codegenModel.parentSchema); - final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); - codegenModel = PkmstServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); - } - return codegenModel; - } - - @Override - public Map postProcessSupportingFileData(Map objs) { - return objs; - } - - @Override - public Map postProcessModels(Map objs) { - // recursively add import for mapping one type to multiple imports - List> recursiveImports = (List>) objs.get("imports"); - if (recursiveImports == null) { - return objs; - } - - ListIterator> listIterator = recursiveImports.listIterator(); - while (listIterator.hasNext()) { - String _import = listIterator.next().get("import"); - // if the import package happens to be found in the importMapping (key) - // add the corresponding import package to the list - if (importMapping.containsKey(_import)) { - Map newImportMap = new HashMap(); - newImportMap.put("import", importMapping.get(_import)); - listIterator.add(newImportMap); - } - } - - return postProcessModelsEnum(objs); - } - - @Override - public void preprocessSwagger(Swagger swagger) { - super.preprocessSwagger(swagger); - if (swagger == null || swagger.getPaths() == null) { - return; - } - if (swagger.getTags() != null) { - System.out.println("Tags are::" + swagger.getTags()); - List resourcePaths = new ArrayList(); - for (Tag tag : swagger.getTags()) { - ResourcePath resourcePath = new ResourcePath(); - resourcePath.setPath(tag.getName()); - resourcePaths.add(resourcePath); - } - this.additionalProperties.put("resourcePaths", resourcePaths); - } - // get vendor extensions - - Map vendorExt = swagger.getInfo().getVendorExtensions(); - if (vendorExt != null && !vendorExt.toString().equals("")) { - if (vendorExt.containsKey("x-codegen")) { - - Map uris = (Map) vendorExt.get("x-codegen"); - if (uris.containsKey("eurekaUri")) { - String eurekaUri = uris.get("eurekaUri"); - additionalProperties.put(EUREKA_URI, eurekaUri); - } - if (uris.containsKey("zipkinUri")) { - String zipkinUri = uris.get("zipkinUri"); - additionalProperties.put(ZIPKIN_URI, zipkinUri); - } - if (uris.containsKey("springBootAdminUri")) { - String springBootAdminUri = uris.get("springBootAdminUri"); - additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); - } - if (uris.containsKey("pkmstInterceptor")) { - String pkmstInterceptor = uris.get("pkmstInterceptor"); - additionalProperties.put("pkmstInterceptor", pkmstInterceptor); - } - } - } - - for (String pathname : swagger.getPaths().keySet()) { - Path path = swagger.getPath(pathname); - if (path.getOperations() == null) { - continue; - } - for (Operation operation : path.getOperations()) { - boolean hasFormParameters = false; - for (Parameter parameter : operation.getParameters()) { - if (parameter instanceof FormParameter) { - hasFormParameters = true; - } - } - // only add content-Type if its no a GET-Method - if (path.getGet() != null || !operation.equals(path.getGet())) { - String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" - : "application/json"; - String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() - ? defaultContentType - : operation.getConsumes().get(0); - operation.setVendorExtension("x-contentType", contentType); - } - String accepts = getAccept(operation); - operation.setVendorExtension("x-accepts", accepts); - } - } - - if ("/".equals(swagger.getBasePath())) { - swagger.setBasePath(""); - } - - if (!additionalProperties.containsKey(TITLE)) { - // From the title, compute a reasonable name for the package and the API - String title = swagger.getInfo().getTitle(); - - // Drop any API suffix - if (title != null) { - title = title.trim().replace(" ", "-"); - if (title.toUpperCase().endsWith("API")) { - title = title.substring(0, title.length() - 3); - } - - this.title = camelize(sanitizeName(title), true); - } - additionalProperties.put(TITLE, this.title); - } - - String host = swagger.getHost(); - String port = "8008"; - if (host != null) { - String[] parts = host.split(":"); - if (parts.length > 1) { - port = parts[1]; - } - } - - this.additionalProperties.put("serverPort", port); - if (swagger.getPaths() != null) { - for (String pathname : swagger.getPaths().keySet()) { - Path path = swagger.getPath(pathname); - if (path.getOperations() != null) { - for (Operation operation : path.getOperations()) { - if (operation.getTags() != null) { - List> tags = new ArrayList>(); - for (String tag : operation.getTags()) { - Map value = new HashMap(); - value.put("tag", tag); - value.put("hasMore", "true"); - tags.add(value); - } - if (tags.size() > 0) { - tags.get(tags.size() - 1).remove("hasMore"); - } - if (operation.getTags().size() > 0) { - String tag = operation.getTags().get(0); - operation.setTags(Arrays.asList(tag)); - } - operation.setVendorExtension("x-tags", tags); - } - } - } - } - } - } - - @Override - public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, - Map> operations) { - String basePath = resourcePath; - if (basePath.startsWith("/")) { - basePath = basePath.substring(1); - } - int pos = basePath.indexOf("/"); - if (pos > 0) { - basePath = basePath.substring(0, pos); - } - - if (basePath.equals("")) { - basePath = "default"; - } else { - co.subresourceOperation = !co.path.isEmpty(); - } - List opList = operations.get(basePath); - if (opList == null) { - opList = new ArrayList(); - operations.put(basePath, opList); - } - opList.add(co); - co.baseName = basePath; - } - - @Override - public String toApiName(String name) { - if (name.length() == 0) { - return "DefaultApi"; - } - name = sanitizeName(name); - return camelize(name) + "Api"; - } - - @Override - public void setParameterExampleValue(CodegenParameter p) { - String type = p.baseType; - if (type == null) { - type = p.dataType; - } - - if ("File".equals(type)) { - String example; - - if (p.defaultValue == null) { - example = p.example; - } else { - example = p.defaultValue; - } - - if (example == null) { - example = "/path/to/file"; - } - example = "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText(example) - + "\"))"; - p.example = example; - } else { - super.setParameterExampleValue(p); - } - } - - @Override - public String escapeReservedWord(String name) { - if (this.reservedWordsMappings().containsKey(name)) { - return this.reservedWordsMappings().get(name); - } - return "_" + name; - } - - @Override - public String apiFileFolder() { - return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); - } - - @Override - public String apiTestFileFolder() { - return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); - } - - @Override - public String modelFileFolder() { - return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); - } - - @Override - public String apiDocFileFolder() { - return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); - } - - @Override - public String modelDocFileFolder() { - return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); - } - - @Override - public String toVarName(String name) { - // sanitize name - name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods - // parameters as 'final'. - - if (name.toLowerCase().matches("^_*class$")) { - return "propertyClass"; - } - - if ("_".equals(name)) { - name = "_u"; - } - - // if it's all uppper case, do nothing - if (name.matches("^[A-Z_]*$")) { - return name; - } - - if (startsWithTwoUppercaseLetters(name)) { - name = name.substring(0, 2).toLowerCase() + name.substring(2); - } - - // camelize (lower first character) the variable name - // pet_id => petId - name = camelize(name, true); - - // for reserved word or word starting with number, append _ - if (isReservedWord(name) || name.matches("^\\d.*")) { - name = escapeReservedWord(name); - } - - return name; - } - - @Override - public String toParamName(String name) { - // to avoid conflicts with 'callback' parameter for async call - if ("callback".equals(name)) { - return "paramCallback"; - } - - // should be the same as variable name - return toVarName(name); - } - - @Override - public String toModelFilename(String name) { - // should be the same as the model name - return toModelName(name); - } - - @Override - public String getTypeDeclaration(Property p) { - if (p instanceof ArrayProperty) { - ArrayProperty ap = (ArrayProperty) p; - Property inner = ap.getItems(); - if (inner == null) { - LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning null - return null; - } - return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; - } else if (p instanceof MapProperty) { - MapProperty mp = (MapProperty) p; - Property inner = mp.getAdditionalProperties(); - if (inner == null) { - LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning null - return null; - } - return getSwaggerType(p) + ""; - } - return super.getTypeDeclaration(p); - } - - @Override - public String toDefaultValue(Property p) { - if (p instanceof ArrayProperty) { - final ArrayProperty ap = (ArrayProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.ArrayList<%s>()"; - } else { - pattern = "new ArrayList<%s>()"; - } - if (ap.getItems() == null) { - return null; - } - - return String.format(pattern, getTypeDeclaration(ap.getItems())); - } else if (p instanceof MapProperty) { - final MapProperty ap = (MapProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.HashMap<%s>()"; - } else { - pattern = "new HashMap<%s>()"; - } - if (ap.getAdditionalProperties() == null) { - return null; - } - - return String.format(pattern, - String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); - } else if (p instanceof IntegerProperty) { - IntegerProperty dp = (IntegerProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - return "null"; - } else if (p instanceof LongProperty) { - LongProperty dp = (LongProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "l"; - } - return "null"; - } else if (p instanceof DoubleProperty) { - DoubleProperty dp = (DoubleProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "d"; - } - return "null"; - } else if (p instanceof FloatProperty) { - FloatProperty dp = (FloatProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "f"; - } - return "null"; - } else if (p instanceof BooleanProperty) { - BooleanProperty bp = (BooleanProperty) p; - if (bp.getDefault() != null) { - return bp.getDefault().toString(); - } - return "null"; - } else if (p instanceof StringProperty) { - StringProperty sp = (StringProperty) p; - if (sp.getDefault() != null) { - String _default = sp.getDefault(); - if (sp.getEnum() == null) { - return "\"" + escapeText(_default) + "\""; - } else { - // convert to enum var name later in postProcessModels - return _default; - } - } - return "null"; - } - return super.toDefaultValue(p); - } - - @Override - public String toExampleValue(Property p) { - if (p.getExample() != null) { - return escapeText(p.getExample().toString()); - } else { - return super.toExampleValue(p); - } - } - - @Override - public String toOperationId(String operationId) { - // throw exception if method name is empty - if (StringUtils.isEmpty(operationId)) { - throw new RuntimeException("Empty method/operation name (operationId) not allowed"); - } - - operationId = camelize(sanitizeName(operationId), true); - - // method name cannot use reserved keyword, e.g. return - if (isReservedWord(operationId)) { - String newOperationId = camelize("call_" + operationId, true); - LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); - return newOperationId; - } - - return operationId; - } - - @Override - protected boolean needToImport(String type) { - return super.needToImport(type) && type.indexOf(".") < 0; - } - - @Override - public String toEnumName(CodegenProperty property) { - return sanitizeName(camelize(property.name)) + "Enum"; - } - - @Override - public String toEnumVarName(String value, String datatype) { - if (value.length() == 0) { - return "EMPTY"; - } - - // for symbol, e.g. $, # - if (getSymbolName(value) != null) { - return getSymbolName(value).toUpperCase(); - } - - // number - if ("Integer".equals(datatype) || "Long".equals(datatype) || "Float".equals(datatype) - || "Double".equals(datatype)) { - String varName = "NUMBER_" + value; - varName = varName.replace("-", "MINUS_"); - varName = varName.replace("\\+", "PLUS_"); - varName = varName.replace("\\.", "_DOT_"); - return varName; - } - - // string - String var = value.replace("\\W+", "_").toUpperCase(); - if (var.matches("\\d.*")) { - return "_" + var; - } else { - return var; - } - } - - @Override - public String toEnumValue(String value, String datatype) { - if ("Integer".equals(datatype) || "Long".equals(datatype) || "Double".equals(datatype)) { - return value; - } else if ("Float".equals(datatype)) { - // add f to number, e.g. 3.14 => 3.14f - return value + "f"; - } else { - return "\"" + escapeText(value) + "\""; - } - } - - @Override - public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, - Map definitions, Swagger swagger) { - CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); - op.path = sanitizePath(op.path); - return op; - } - - @Override - public String escapeQuotationMark(String input) { - // remove " to avoid code injection - return input.replace("\"", ""); - } - - @Override - public String escapeUnsafeCharacters(String input) { - return input.replace("*/", "*_/").replace("/*", "/_*"); - } - - public boolean convertPropertyToBoolean(String propertyKey) { - boolean booleanValue = false; - if (additionalProperties.containsKey(propertyKey)) { - booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); - } - - return booleanValue; - } - - public String toRegularExpression(String pattern) { - return escapeText(pattern); - } - - @Override - public String sanitizeTag(String tag) { - return camelize(sanitizeName(tag)); - } - - public String toBooleanGetter(String name) { - return "is" + getterAndSetterCapitalize(name); - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getArtifactId() { - return artifactId; - } - - public void setArtifactId(String artifactId) { - this.artifactId = artifactId; - } - - public String getArtifactVersion() { - return artifactVersion; - } - - public void setArtifactVersion(String artifactVersion) { - this.artifactVersion = artifactVersion; - } - - public String getProjectFolder() { - return projectFolder; - } - - public void setProjectFolder(String projectFolder) { - this.projectFolder = projectFolder; - } - - public String getEurekaUri() { - return eurekaUri; - } - - public void setEurekaUri(String eurekaUri) { - this.eurekaUri = eurekaUri; - } - - public String getZipkinUri() { - return zipkinUri; - } - - public void setZipkinUri(String zipkinUri) { - this.zipkinUri = zipkinUri; - } - - public String getSpringBootAdminUri() { - return springBootAdminUri; - } - - public void setSpringBootAdminUri(String springBootAdminUri) { - this.springBootAdminUri = springBootAdminUri; - } - - public String getProjectTestFolder() { - return projectTestFolder; - } - - public void setProjectTestFolder(String projectTestFolder) { - this.projectTestFolder = projectTestFolder; - } - - public String getSourceFolder() { - return sourceFolder; - } - - public void setSourceFolder(String sourceFolder) { - this.sourceFolder = sourceFolder; - } - - public String getTestFolder() { - return testFolder; - } - - public void setTestFolder(String testFolder) { - this.testFolder = testFolder; - } + public static final String FULL_JAVA_UTIL = "fullJavaUtil"; + public static final String SUPPORT_JAVA6 = "supportJava6"; + public static final String CONFIG_PACKAGE = "configPackage"; + public static final String BASE_PACKAGE = "basePackage"; + public static final String TITLE = "title"; + public static final String WITH_XML = "withXml"; + public static final String EUREKA_URI = "eurekaUri"; + public static final String ZIPKIN_URI = "zipkinUri"; + public static final String SPRINGADMIN_URI = "springBootAdminUri"; + protected String groupId = "com.prokarma"; + protected String artifactId = "pkmst-microservice"; + protected String artifactVersion = "1.0.0"; + protected String projectFolder; + + protected String projectTestFolder; + protected String sourceFolder; + protected String testFolder; + protected String basePackage = "com.prokarma.pkmst"; + protected String serviceName = "Pkmst"; + protected String configPackage = "com.prokarma.pkmst.config"; + protected boolean implicitHeaders = false; + protected boolean serializeBigDecimalAsString = false; + protected boolean withXml = false; + protected boolean fullJavaUtil; + protected String javaUtilPrefix = ""; + protected Boolean serializableModel = false; + protected String invokerPackage; + protected String title; + protected String apiDocPath = "docs/"; + protected String modelDocPath = "docs/"; + protected String eurekaUri; + protected String zipkinUri; + protected String springBootAdminUri; + + public PkmstServerCodegen() { + super(); + this.projectFolder = "src" + File.separator + "main"; + this.projectTestFolder = "src" + File.separator + "test"; + this.sourceFolder = this.projectFolder + File.separator + "java"; + this.testFolder = this.projectTestFolder + File.separator + "java"; + embeddedTemplateDir = templateDir = "pkmst"; + apiPackage = "com.prokarma.pkmst.controller"; + modelPackage = "com.prokarma.pkmst.model"; + invokerPackage = "com.prokarma.pkmst.controller"; + setReservedWordsLowerCase(Arrays.asList( + // used as internal variables, can collide with parameter names + "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", "localVarHeaderParams", + "localVarFormParams", "localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes", + "localVarContentType", "localVarAuthNames", "localReturnType", "ApiClient", "ApiException", + "ApiResponse", "Configuration", "StringUtil", + + // language reserved words + "abstract", "continue", "for", "new", "switch", "assert", "default", "if", "package", "synchronized", + "boolean", "do", "goto", "private", "this", "break", "double", "implements", "protected", "throw", + "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", + "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while", "null")); + + this.languageSpecificPrimitives = new HashSet(Arrays.asList("String", "boolean", "Boolean", "Double", + "Integer", "Long", "Float", "Object", "byte[]")); + this.instantiationTypes.put("array", "ArrayList"); + this.instantiationTypes.put("map", "HashMap"); + this.typeMapping.put("date", "Date"); + this.typeMapping.put("file", "File"); + + this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); + this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); + this.cliOptions.add(new CliOption("serviceName", "Service Name")); + this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); + this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); + this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); + this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); + // Middleware config + this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); + this.apiTestTemplateFiles.put("api_test.mustache", ".java"); + this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); + this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); + } + + private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { + // This generator uses inline classes to define enums, which breaks when + // dealing with models that have subTypes. To clean this up, we will analyze + // the parent and child models, look for enums that match, and remove + // them from the child models and leave them in the parent. + // Because the child models extend the parents, the enums will be available via + // the parent. + + // Only bother with reconciliation if the parent model has enums. + if (!parentCodegenModel.hasEnums) { + return codegenModel; + } + + // Get the properties for the parent and child models + final List parentModelCodegenProperties = parentCodegenModel.vars; + List codegenProperties = codegenModel.vars; + + // Iterate over all of the parent model properties + boolean removedChildEnum = false; + for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { + // Look for enums + if (parentModelCodegenPropery.isEnum) { + // Now that we have found an enum in the parent class, + // and search the child class for the same enum. + Iterator iterator = codegenProperties.iterator(); + while (iterator.hasNext()) { + CodegenProperty codegenProperty = iterator.next(); + if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { + // We found an enum in the child class that is + // a duplicate of the one in the parent, so remove it. + iterator.remove(); + removedChildEnum = true; + } + } + } + } + + if (removedChildEnum) { + // If we removed an entry from this model's vars, we need to ensure hasMore is + // updated + int count = 0, numVars = codegenProperties.size(); + for (CodegenProperty codegenProperty : codegenProperties) { + count += 1; + codegenProperty.hasMore = (count < numVars) ? true : false; + } + codegenModel.vars = codegenProperties; + } + return codegenModel; + } + + private static String getAccept(Operation operation) { + String accepts = null; + String defaultContentType = "application/json"; + if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String produces : operation.getProduces()) { + if (defaultContentType.equalsIgnoreCase(produces)) { + accepts = defaultContentType; + break; + } else { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(produces); + } + } + if (accepts == null) { + accepts = sb.toString(); + } + } else { + accepts = defaultContentType; + } + + return accepts; + } + + public CodegenType getTag() { + return CodegenType.SERVER; + } + + public String getName() { + return "pkmst"; + } + + public String getHelp() { + return "Generates a Java SpringBoot Server application using the SpringFox integration." + + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; + } + + public void processOpts() { + super.processOpts(); + if (this.additionalProperties.containsKey("basePackage")) { + this.setBasePackage((String) this.additionalProperties.get("basePackage")); + this.setInvokerPackage(this.getBasePackage()); + this.apiPackage = this.getBasePackage() + ".controller"; + this.modelPackage = this.getBasePackage() + ".model"; + this.setConfigPackage(this.getBasePackage() + ".config"); + + // this.additionalProperties.put(BASE_PACKAGE, this.getBasePackage()); + } else { + this.additionalProperties.put(BASE_PACKAGE, basePackage); + this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); + this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); + this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); + this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + } + if (this.additionalProperties.containsKey("groupId")) { + this.setGroupId((String) this.additionalProperties.get("groupId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.GROUP_ID, groupId); + } + if (this.additionalProperties.containsKey("artifactId")) { + this.setArtifactId((String) this.additionalProperties.get("artifactId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); + } + if (this.additionalProperties.containsKey("artifactVersion")) { + this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + } + if (this.additionalProperties.containsKey("serviceName")) { + this.setServiceName((String) this.additionalProperties.get("serviceName")); + } else { + // not set, use to be passed to template + additionalProperties.put("serviceName", serviceName); + } + + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { + this.setSerializeBigDecimalAsString(Boolean.valueOf( + this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); + } + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { + this.setSerializableModel( + Boolean.valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); + } + if (this.additionalProperties.containsKey(TITLE)) { + this.setTitle((String) this.additionalProperties.get(TITLE)); + } + this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); + if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { + this.setFullJavaUtil(Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); + } + + if (this.additionalProperties.containsKey(EUREKA_URI)) { + this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); + } + if (this.additionalProperties.containsKey(ZIPKIN_URI)) { + this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); + } + if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { + this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); + } + if (fullJavaUtil) { + javaUtilPrefix = "java.util."; + } + this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); + this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); + this.additionalProperties.put(SUPPORT_JAVA6, false); + this.additionalProperties.put("java8", true); + + if (this.additionalProperties.containsKey(WITH_XML)) { + this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); + } + this.additionalProperties.put(WITH_XML, withXml); + + // make api and model doc path available in mustache template + this.additionalProperties.put("apiDocPath", apiDocPath); + this.additionalProperties.put("modelDocPath", modelDocPath); + + this.importMapping.put("List", "java.util.List"); + + if (fullJavaUtil) { + this.typeMapping.put("array", "java.util.List"); + this.typeMapping.put("map", "java.util.Map"); + this.typeMapping.put("DateTime", "java.util.Date"); + this.typeMapping.put("UUID", "java.util.UUID"); + this.typeMapping.remove("List"); + this.importMapping.remove("Date"); + this.importMapping.remove("Map"); + this.importMapping.remove("HashMap"); + this.importMapping.remove("Array"); + this.importMapping.remove("ArrayList"); + this.importMapping.remove("List"); + this.importMapping.remove("Set"); + this.importMapping.remove("DateTime"); + this.importMapping.remove("UUID"); + this.instantiationTypes.put("array", "java.util.ArrayList"); + this.instantiationTypes.put("map", "java.util.HashMap"); + } + // optional jackson mappings for BigDecimal support + this.importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); + this.importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); + + // imports for pojos + this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); + this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); + this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); + this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); + this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); + this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); + this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); + this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); + this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); + this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); + this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); + this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); + this.importMapping.put("IOException", "java.io.IOException"); + this.importMapping.put("Objects", "java.util.Objects"); + this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); + // import JsonCreator if JsonProperty is imported + // used later in recursive import in postProcessingModels + this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", + "com.fasterxml.jackson.annotation.JsonCreator"); + + this.apiTemplateFiles.put("api.mustache", ".java"); + this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); + + this.modelTemplateFiles.put("model.mustache", ".java"); + + this.supportingFiles.add(new SupportingFile("SpringBootApplication.mustache", + (this.getSourceFolder() + File.separator + this.getBasePackage()).replace(".", File.separator), + this.getServiceName() + "Application" + ".java")); + + this.supportingFiles + .add(new SupportingFile("config" + File.separator + "swaggerDocumentationConfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", + java.io.File.separator) + File.separator + "swagger", + "SwaggerDocumentationConfig.java")); + + this.supportingFiles.add(new SupportingFile("config" + File.separator + "pkmstproperties.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator + "swagger", + "PkmstProperties.java")); + this.supportingFiles.add(new SupportingFile("config" + File.separator + "appconfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator, + "AppConfig.java")); + + // Security + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "authorizationServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "AuthorizationServerConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "oAuth2SecurityConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "OAuth2SecurityConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "resourceServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "ResourceServerConfiguration.java")); + + // logging + + this.supportingFiles.add(new SupportingFile("logging" + File.separator + "httpLoggingFilter.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + File.separator + + "logging", + "HttpLoggingFilter.java")); + + // Resources + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-local.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-local.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev-config.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev-config.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "bootstrap.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + + // POM + this.supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + + // Readme + this.supportingFiles.add(new SupportingFile("readme.mustache", "", "Readme.md")); + + // manifest + + this.supportingFiles.add(new SupportingFile("manifest.mustache", "", "manifest.yml")); + + // docker + this.supportingFiles.add(new SupportingFile("docker.mustache", "", "Dockerfile")); + + // logstash + + this.supportingFiles.add(new SupportingFile("logstash.mustache", "", "logstash.conf")); + + // Cucumber + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "executeReport.mustache", + this.testFolder + File.separator + this.basePackage.replace(".", File.separator) + File.separator + + "cucumber" + File.separator + "report", + "ExecuteReport.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberTest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Test.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberSteps.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Steps.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "package.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "package-info.java")); + + // test resources + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "cucumber.mustache", + (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "cucumber", + serviceName + ".feature")); + + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "bootstrap.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.properties")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application-test.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application-test.properties")); + + // Gatling + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "gatling.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "gatling.conf")); + + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.conf")); + + this.supportingFiles.add(new SupportingFile( + "gatling" + File.separator + "testapi.mustache", ("src") + File.separator + ("test") + File.separator + + ("scala") + File.separator + ("scalaFiles").replace(".", java.io.File.separator), + "testapi.scala")); + + /* + * this.supportingFiles.add(new SupportingFile( "gatling" + File.separator + + * "package.mustache", ("src")+ File.separator + ("test")+ File.separator + + * ("scala")+ File.separator + ("scalaFiles").replace(".", + * java.io.File.separator), "package.info")); + */ + + // adding class for integration test + this.supportingFiles.add(new SupportingFile( + "integration" + File.separator + "integrationtest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "controller", + serviceName + "IT.java")); + } + + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (final CodegenOperation operation : ops) { + List responses = operation.responses; + if (responses != null) { + for (final CodegenResponse resp : responses) { + if ("0".equals(resp.code)) { + resp.code = "200"; + } + doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + resp.dataType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + resp.containerType = returnContainer; + } + }); + } + } + + doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + operation.returnType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + operation.returnContainer = returnContainer; + } + }); + + if (implicitHeaders) { + removeHeadersFromAllParams(operation.allParams); + } + } + } + + return objs; + } + + /** + * This method removes header parameters from the list of parameters and also + * corrects last allParams hasMore state. + * + * @param allParams + * list of all parameters + */ + private void removeHeadersFromAllParams(List allParams) { + if (allParams.isEmpty()) { + return; + } + final ArrayList copy = new ArrayList(allParams); + allParams.clear(); + + for (CodegenParameter p : copy) { + if (!p.isHeaderParam) { + allParams.add(p); + } + } + allParams.get(allParams.size() - 1).hasMore = false; + } + + /** + * @param returnType + * The return type that needs to be converted + * @param dataTypeAssigner + * An object that will assign the data to the respective fields in + * the model. + */ + private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { + final String rt = returnType; + if (rt == null) { + dataTypeAssigner.setReturnType("Void"); + } else if (rt.startsWith("List")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("List"); + } + } else if (rt.startsWith("Map")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); + dataTypeAssigner.setReturnContainer("Map"); + } + } else if (rt.startsWith("Set")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("Set"); + } + } + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + + swaggerType = getAlias(swaggerType); + + // don't apply renaming on types from the typeMapping + if (this.typeMapping.containsKey(swaggerType)) { + return this.typeMapping.get(swaggerType); + } + + if (null == swaggerType) { + LOGGER.error("No Type defined for Property " + p); + } + return toModelName(swaggerType); + } + + @Override + public String getAlias(String name) { + if (typeAliases.containsKey(name)) { + return typeAliases.get(name); + } + return name; + } + + @Override + public String toModelName(final String name) { + // We need to check if import-mapping has a different model for this class, so + // we use it + // instead of the auto-generated one. + if (this.importMapping.containsKey(name)) { + return this.importMapping.get(name); + } + + final String sanitizedName = sanitizeName(name); + + String nameWithPrefixSuffix = sanitizedName; + if (!StringUtils.isEmpty(modelNamePrefix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; + } + + if (!StringUtils.isEmpty(modelNameSuffix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; + } + + // camelize the model name + // phone_number => PhoneNumber + final String camelizedName = camelize(nameWithPrefixSuffix); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(camelizedName)) { + final String modelName = "Model" + camelizedName; + LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); + return modelName; + } + + // model name starts with number + if (camelizedName.matches("^\\d.*")) { + final String modelName = "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize) + LOGGER.warn( + name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName); + return modelName; + } + + return camelizedName; + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + if (serializeBigDecimalAsString) { + if (property.baseType.equals("BigDecimal")) { + // we serialize BigDecimal as `string` to avoid precision loss + property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); + + // this requires some more imports to be added for this model... + model.imports.add("ToStringSerializer"); + model.imports.add("JsonSerialize"); + } + } + + if (!fullJavaUtil) { + if ("array".equals(property.containerType)) { + model.imports.add("ArrayList"); + } else if ("map".equals(property.containerType)) { + model.imports.add("HashMap"); + } + } + + if (!BooleanUtils.toBoolean(model.isEnum)) { + // needed by all pojos, but not enums + model.imports.add("ApiModelProperty"); + model.imports.add("ApiModel"); + } + + // super.postProcessModelProperty(model, property); + + if ("null".equals(property.example)) { + property.example = null; + } + + // Add imports for Jackson + if (!Boolean.TRUE.equals(model.isEnum)) { + model.imports.add("JsonProperty"); + + if (Boolean.TRUE.equals(model.hasEnums)) { + model.imports.add("JsonValue"); + } + } else { // enum class + // Needed imports for Jackson's JsonCreator + if (this.additionalProperties.containsKey("jackson")) { + model.imports.add("JsonCreator"); + } + } + } + + @Override + public Map postProcessModelsEnum(Map objs) { + objs = super.postProcessModelsEnum(objs); + + // Add imports for Jackson + List> imports = (List>) objs.get("imports"); + List models = (List) objs.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + // for enum model + if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { + cm.imports.add(this.importMapping.get("JsonValue")); + Map item = new HashMap(); + item.put("import", this.importMapping.get("JsonValue")); + imports.add(item); + } + } + + return objs; + } + + @Override + public CodegenModel fromModel(String name, Model model, Map allDefinitions) { + CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); + if (codegenModel.description != null) { + codegenModel.imports.add("ApiModel"); + } + if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { + codegenModel.imports.add("JsonSubTypes"); + codegenModel.imports.add("JsonTypeInfo"); + } + if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { + final Model parentModel = allDefinitions.get(codegenModel.parentSchema); + final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); + codegenModel = PkmstServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); + } + return codegenModel; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + return objs; + } + + @Override + public Map postProcessModels(Map objs) { + // recursively add import for mapping one type to multiple imports + List> recursiveImports = (List>) objs.get("imports"); + if (recursiveImports == null) { + return objs; + } + + ListIterator> listIterator = recursiveImports.listIterator(); + while (listIterator.hasNext()) { + String _import = listIterator.next().get("import"); + // if the import package happens to be found in the importMapping (key) + // add the corresponding import package to the list + if (importMapping.containsKey(_import)) { + Map newImportMap = new HashMap(); + newImportMap.put("import", importMapping.get(_import)); + listIterator.add(newImportMap); + } + } + + return postProcessModelsEnum(objs); + } + + @Override + public void preprocessSwagger(Swagger swagger) { + super.preprocessSwagger(swagger); + if (swagger == null || swagger.getPaths() == null) { + return; + } + if (swagger.getTags() != null) { + System.out.println("Tags are::" + swagger.getTags()); + List resourcePaths = new ArrayList(); + for (Tag tag : swagger.getTags()) { + ResourcePath resourcePath = new ResourcePath(); + resourcePath.setPath(tag.getName()); + resourcePaths.add(resourcePath); + } + this.additionalProperties.put("resourcePaths", resourcePaths); + } + // get vendor extensions + + Map vendorExt = swagger.getInfo().getVendorExtensions(); + if (vendorExt != null && !vendorExt.toString().equals("")) { + if (vendorExt.containsKey("x-codegen")) { + + Map uris = (Map) vendorExt.get("x-codegen"); + if (uris.containsKey("eurekaUri")) { + String eurekaUri = uris.get("eurekaUri"); + additionalProperties.put(EUREKA_URI, eurekaUri); + } + if (uris.containsKey("zipkinUri")) { + String zipkinUri = uris.get("zipkinUri"); + additionalProperties.put(ZIPKIN_URI, zipkinUri); + } + if (uris.containsKey("springBootAdminUri")) { + String springBootAdminUri = uris.get("springBootAdminUri"); + additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); + } + if (uris.containsKey("pkmstInterceptor")) { + String pkmstInterceptor = uris.get("pkmstInterceptor"); + additionalProperties.put("pkmstInterceptor", pkmstInterceptor); + } + } + } + + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() == null) { + continue; + } + for (Operation operation : path.getOperations()) { + boolean hasFormParameters = false; + for (Parameter parameter : operation.getParameters()) { + if (parameter instanceof FormParameter) { + hasFormParameters = true; + } + } + // only add content-Type if its no a GET-Method + if (path.getGet() != null || !operation.equals(path.getGet())) { + String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" + : "application/json"; + String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() + ? defaultContentType + : operation.getConsumes().get(0); + operation.setVendorExtension("x-contentType", contentType); + } + String accepts = getAccept(operation); + operation.setVendorExtension("x-accepts", accepts); + } + } + + if ("/".equals(swagger.getBasePath())) { + swagger.setBasePath(""); + } + + if (!additionalProperties.containsKey(TITLE)) { + // From the title, compute a reasonable name for the package and the API + String title = swagger.getInfo().getTitle(); + + // Drop any API suffix + if (title != null) { + title = title.trim().replace(" ", "-"); + if (title.toUpperCase().endsWith("API")) { + title = title.substring(0, title.length() - 3); + } + + this.title = camelize(sanitizeName(title), true); + } + additionalProperties.put(TITLE, this.title); + } + + String host = swagger.getHost(); + String port = "8008"; + if (host != null) { + String[] parts = host.split(":"); + if (parts.length > 1) { + port = parts[1]; + } + } + + this.additionalProperties.put("serverPort", port); + if (swagger.getPaths() != null) { + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() != null) { + for (Operation operation : path.getOperations()) { + if (operation.getTags() != null) { + List> tags = new ArrayList>(); + for (String tag : operation.getTags()) { + Map value = new HashMap(); + value.put("tag", tag); + value.put("hasMore", "true"); + tags.add(value); + } + if (tags.size() > 0) { + tags.get(tags.size() - 1).remove("hasMore"); + } + if (operation.getTags().size() > 0) { + String tag = operation.getTags().get(0); + operation.setTags(Arrays.asList(tag)); + } + operation.setVendorExtension("x-tags", tags); + } + } + } + } + } + } + + @Override + public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, + Map> operations) { + String basePath = resourcePath; + if (basePath.startsWith("/")) { + basePath = basePath.substring(1); + } + int pos = basePath.indexOf("/"); + if (pos > 0) { + basePath = basePath.substring(0, pos); + } + + if (basePath.equals("")) { + basePath = "default"; + } else { + co.subresourceOperation = !co.path.isEmpty(); + } + List opList = operations.get(basePath); + if (opList == null) { + opList = new ArrayList(); + operations.put(basePath, opList); + } + opList.add(co); + co.baseName = basePath; + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultApi"; + } + name = sanitizeName(name); + return camelize(name) + "Api"; + } + + @Override + public void setParameterExampleValue(CodegenParameter p) { + String type = p.baseType; + if (type == null) { + type = p.dataType; + } + + if ("File".equals(type)) { + String example; + + if (p.defaultValue == null) { + example = p.example; + } else { + example = p.defaultValue; + } + + if (example == null) { + example = "/path/to/file"; + } + example = "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText(example) + + "\"))"; + p.example = example; + } else { + super.setParameterExampleValue(p); + } + } + + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; + } + + @Override + public String apiFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String apiTestFileFolder() { + return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String modelFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); + } + + @Override + public String apiDocFileFolder() { + return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); + } + + @Override + public String modelDocFileFolder() { + return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods + // parameters as 'final'. + + if (name.toLowerCase().matches("^_*class$")) { + return "propertyClass"; + } + + if ("_".equals(name)) { + name = "_u"; + } + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + if (startsWithTwoUppercaseLetters(name)) { + name = name.substring(0, 2).toLowerCase() + name.substring(2); + } + + // camelize (lower first character) the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved word or word starting with number, append _ + if (isReservedWord(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public String toParamName(String name) { + // to avoid conflicts with 'callback' parameter for async call + if ("callback".equals(name)) { + return "paramCallback"; + } + + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + if (inner == null) { + LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning null + return null; + } + return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + if (inner == null) { + LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning null + return null; + } + return getSwaggerType(p) + ""; + } + return super.getTypeDeclaration(p); + } + + @Override + public String toDefaultValue(Property p) { + if (p instanceof ArrayProperty) { + final ArrayProperty ap = (ArrayProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.ArrayList<%s>()"; + } else { + pattern = "new ArrayList<%s>()"; + } + if (ap.getItems() == null) { + return null; + } + + return String.format(pattern, getTypeDeclaration(ap.getItems())); + } else if (p instanceof MapProperty) { + final MapProperty ap = (MapProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.HashMap<%s>()"; + } else { + pattern = "new HashMap<%s>()"; + } + if (ap.getAdditionalProperties() == null) { + return null; + } + + return String.format(pattern, + String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); + } else if (p instanceof IntegerProperty) { + IntegerProperty dp = (IntegerProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + return "null"; + } else if (p instanceof LongProperty) { + LongProperty dp = (LongProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "l"; + } + return "null"; + } else if (p instanceof DoubleProperty) { + DoubleProperty dp = (DoubleProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "d"; + } + return "null"; + } else if (p instanceof FloatProperty) { + FloatProperty dp = (FloatProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "f"; + } + return "null"; + } else if (p instanceof BooleanProperty) { + BooleanProperty bp = (BooleanProperty) p; + if (bp.getDefault() != null) { + return bp.getDefault().toString(); + } + return "null"; + } else if (p instanceof StringProperty) { + StringProperty sp = (StringProperty) p; + if (sp.getDefault() != null) { + String _default = sp.getDefault(); + if (sp.getEnum() == null) { + return "\"" + escapeText(_default) + "\""; + } else { + // convert to enum var name later in postProcessModels + return _default; + } + } + return "null"; + } + return super.toDefaultValue(p); + } + + @Override + public String toExampleValue(Property p) { + if (p.getExample() != null) { + return escapeText(p.getExample().toString()); + } else { + return super.toExampleValue(p); + } + } + + @Override + public String toOperationId(String operationId) { + // throw exception if method name is empty + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method/operation name (operationId) not allowed"); + } + + operationId = camelize(sanitizeName(operationId), true); + + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + String newOperationId = camelize("call_" + operationId, true); + LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); + return newOperationId; + } + + return operationId; + } + + @Override + protected boolean needToImport(String type) { + return super.needToImport(type) && type.indexOf(".") < 0; + } + + @Override + public String toEnumName(CodegenProperty property) { + return sanitizeName(camelize(property.name)) + "Enum"; + } + + @Override + public String toEnumVarName(String value, String datatype) { + if (value.length() == 0) { + return "EMPTY"; + } + + // for symbol, e.g. $, # + if (getSymbolName(value) != null) { + return getSymbolName(value).toUpperCase(); + } + + // number + if ("Integer".equals(datatype) || "Long".equals(datatype) || "Float".equals(datatype) + || "Double".equals(datatype)) { + String varName = "NUMBER_" + value; + varName = varName.replace("-", "MINUS_"); + varName = varName.replace("\\+", "PLUS_"); + varName = varName.replace("\\.", "_DOT_"); + return varName; + } + + // string + String var = value.replace("\\W+", "_").toUpperCase(); + if (var.matches("\\d.*")) { + return "_" + var; + } else { + return var; + } + } + + @Override + public String toEnumValue(String value, String datatype) { + if ("Integer".equals(datatype) || "Long".equals(datatype) || "Double".equals(datatype)) { + return value; + } else if ("Float".equals(datatype)) { + // add f to number, e.g. 3.14 => 3.14f + return value + "f"; + } else { + return "\"" + escapeText(value) + "\""; + } + } + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, + Map definitions, Swagger swagger) { + CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); + op.path = sanitizePath(op.path); + return op; + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + public boolean convertPropertyToBoolean(String propertyKey) { + boolean booleanValue = false; + if (additionalProperties.containsKey(propertyKey)) { + booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); + } + + return booleanValue; + } + + public String toRegularExpression(String pattern) { + return escapeText(pattern); + } + + @Override + public String sanitizeTag(String tag) { + return camelize(sanitizeName(tag)); + } + + public String toBooleanGetter(String name) { + return "is" + getterAndSetterCapitalize(name); + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getArtifactVersion() { + return artifactVersion; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public String getProjectFolder() { + return projectFolder; + } + + public void setProjectFolder(String projectFolder) { + this.projectFolder = projectFolder; + } + + public String getEurekaUri() { + return eurekaUri; + } + + public void setEurekaUri(String eurekaUri) { + this.eurekaUri = eurekaUri; + } + + public String getZipkinUri() { + return zipkinUri; + } + + public void setZipkinUri(String zipkinUri) { + this.zipkinUri = zipkinUri; + } + + public String getSpringBootAdminUri() { + return springBootAdminUri; + } + + public void setSpringBootAdminUri(String springBootAdminUri) { + this.springBootAdminUri = springBootAdminUri; + } + + public String getProjectTestFolder() { + return projectTestFolder; + } + + public void setProjectTestFolder(String projectTestFolder) { + this.projectTestFolder = projectTestFolder; + } + + public String getSourceFolder() { + return sourceFolder; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } + + public String getTestFolder() { + return testFolder; + } + + public void setTestFolder(String testFolder) { + this.testFolder = testFolder; + } - public String getBasePackage() { - return basePackage; - } + public String getBasePackage() { + return basePackage; + } - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - } + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } - public String getServiceName() { - return serviceName; - } + public String getServiceName() { + return serviceName; + } - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } - public String getConfigPackage() { - return configPackage; - } + public String getConfigPackage() { + return configPackage; + } - public void setConfigPackage(String configPackage) { - this.configPackage = configPackage; - } + public void setConfigPackage(String configPackage) { + this.configPackage = configPackage; + } - public boolean isImplicitHeaders() { - return implicitHeaders; - } + public boolean isImplicitHeaders() { + return implicitHeaders; + } - public void setImplicitHeaders(boolean implicitHeaders) { - this.implicitHeaders = implicitHeaders; - } + public void setImplicitHeaders(boolean implicitHeaders) { + this.implicitHeaders = implicitHeaders; + } - public boolean isSerializeBigDecimalAsString() { - return serializeBigDecimalAsString; - } + public boolean isSerializeBigDecimalAsString() { + return serializeBigDecimalAsString; + } - public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { - this.serializeBigDecimalAsString = serializeBigDecimalAsString; - } + public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { + this.serializeBigDecimalAsString = serializeBigDecimalAsString; + } - public boolean isFullJavaUtil() { - return fullJavaUtil; - } + public boolean isFullJavaUtil() { + return fullJavaUtil; + } - public void setFullJavaUtil(boolean fullJavaUtil) { - this.fullJavaUtil = fullJavaUtil; - } + public void setFullJavaUtil(boolean fullJavaUtil) { + this.fullJavaUtil = fullJavaUtil; + } - public Boolean getSerializableModel() { - return serializableModel; - } + public Boolean getSerializableModel() { + return serializableModel; + } - public void setSerializableModel(Boolean serializableModel) { - this.serializableModel = serializableModel; - } + public void setSerializableModel(Boolean serializableModel) { + this.serializableModel = serializableModel; + } - public String getInvokerPackage() { - return invokerPackage; - } + public String getInvokerPackage() { + return invokerPackage; + } - public void setInvokerPackage(String invokerPackage) { - this.invokerPackage = invokerPackage; - } + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } - public String getTitle() { - return title; - } + public String getTitle() { + return title; + } - public void setTitle(String title) { - this.title = title; - } + public void setTitle(String title) { + this.title = title; + } - public boolean isWithXml() { - return withXml; - } + public boolean isWithXml() { + return withXml; + } - public void setWithXml(boolean withXml) { - this.withXml = withXml; - } + public void setWithXml(boolean withXml) { + this.withXml = withXml; + } - private boolean startsWithTwoUppercaseLetters(String name) { - boolean startsWithTwoUppercaseLetters = false; - if (name.length() > 1) { - startsWithTwoUppercaseLetters = name.substring(0, 2).equals(name.substring(0, 2).toUpperCase()); - } - return startsWithTwoUppercaseLetters; - } + private boolean startsWithTwoUppercaseLetters(String name) { + boolean startsWithTwoUppercaseLetters = false; + if (name.length() > 1) { + startsWithTwoUppercaseLetters = name.substring(0, 2).equals(name.substring(0, 2).toUpperCase()); + } + return startsWithTwoUppercaseLetters; + } - private String sanitizePath(String p) { - // prefer replace a ", instead of a fuLL URL encode for readability - return p.replace("\"", "%22"); - } + private String sanitizePath(String p) { + // prefer replace a ", instead of a fuLL URL encode for readability + return p.replace("\"", "%22"); + } - private interface DataTypeAssigner { + private interface DataTypeAssigner { - void setReturnType(String returnType); + void setReturnType(String returnType); - void setReturnContainer(String returnContainer); - } + void setReturnContainer(String returnContainer); + } - private class ResourcePath { + private class ResourcePath { - private String path; + private String path; - public String getPath() { - return path; - } + public String getPath() { + return path; + } - public void setPath(String path) { - this.path = path; - } + public void setPath(String path) { + this.path = path; + } - @Override - public String toString() { - return this.path; - } - } + @Override + public String toString() { + return this.path; + } + } } From bfe268544c9760beb0fcbeb6782effad21e66e84 Mon Sep 17 00:00:00 2001 From: ninod Date: Wed, 22 Nov 2017 14:29:24 -0600 Subject: [PATCH 04/19] adding documentation folder --- .../pkmst/docs/pkmstswaggercodegendiagram1.PNG | Bin 0 -> 44657 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/docs/pkmstswaggercodegendiagram1.PNG diff --git a/modules/swagger-codegen/src/main/resources/pkmst/docs/pkmstswaggercodegendiagram1.PNG b/modules/swagger-codegen/src/main/resources/pkmst/docs/pkmstswaggercodegendiagram1.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f7a3cc491ad3401a76de792ac1591ce24ea633f8 GIT binary patch literal 44657 zcmcG$2|SeR`#-MCVU!p-g=~YOQYdAOX;A4TiVB6Xl}h#ygAuZ%6WWkvS{%xfP?ju1 z$Uak9#!j-tSYpgD`|lpqSw83c`F&sirPoVo=6UYtzOVaQ-q-uO?kDDy>9I{4wr$|y z;n{TD*vOoR2ZH3`SuY9Y1D`-LLNVZtZVRi;mpJHito4)^2`mp8P>*9=}GIMnBNA>{mc74%;2ky)XCeElVRSQ z_p7@IDG^drw+jo1i5i}meRN*3A&Z+hOp!PoJkmPa`L zuwuM=G4z9XgXU~)ryDxQ*WrS9+%|au&$PgtsT{hBM;_fT&*N-oHl39|v1DA{Rh~U~ z_N`wYon4;Y_0;5xFnd^dgVXZ2wzxAKS0%rYmm~;%V@#gtH`VRMrcZG3-8whf29E#j z!|~5U{D|)Y1o<#PM~ z=c6JFVA6jsFv$QD0oQ(+D7iM@!x*^&-}S6pb$?yNzkUeolTEDswz9~T@8ADQSAaAf zuk8Q73+&HD{;OymHn2p(MlKXe`}+1VPLu&z z{pF^tkFs*c?o&X4Viv`=T~PXrx_m9o81uBiSDtn2zkc|EdJOvP#GhAMe2Z&w_zs6>+GF$vD%k@)Kt+^q#|B{ny_zQ67?gA@O8?4rR!*f;!S^;70GfVA(NwzOtjZZQ@CL z!}(ccW*j9D@rGkVS{ambsLNY;e{e3bg}T=*$L!$We$$PbNuih4<%9W+9-b!VE6B@_ zSpBB<`Gb@}Jn9{LV>I~lHUbX*-uMUx5fKqd%#f1J&{vr!owE~qE*&oiu2;j;yv1oJ z;{3jcgX>xzaH_VM*xQC{7Q`4^U83Az!??H!kh~Gfpjy5|Z|2Hpa@fP*F_7Ou}V4Zkf%o9iSQ-uij>k z|Mg_B%?Q!U>5Ng`!Js7urmWZJz0|&^jaJCj=hW>u4ldR5x)>@*K2kh~qgf(sm^p5o zlRqBZ;s6s-Qju${C@9Idk$GOpuQ8db8ujJF3oxy3+>5ll1dxyFX&VWGfma0Opz`wa zDoscOn6~kJWq=bF%zK|f*-gbg{61G&Pa&gM1gRRdc+`*8OP+EnUIAF0~`xp|ULZe`m_w+n!~l~gp3{^DS<1WopVz8_Qj>$=C=kc7qK z!ErF|W`W)87vCb{HL@_HMjn46XFPSnsdV4&9|BRYq0XlD^-#oSv-zE)qq`gRz!b1E zDf^)b2;-rAbLo8TMqchh1~!LP?;e$r>t!f*X%C4;cz|($h6x~7B+b3Twek1UPh)*m ze*fnhzZ%BJ_S_eiR^h8FK4yw-dv$h8Ww&l(npUto<&fjmE=SdJ>KRy&H5pd@M1 zk=pSzZMtVF%QwO8jS8t>A!5}Yw+{jR*7Ev_lRhe&iX+9KiyE+1Hmo;tP-NhJd5DM! z>{(^hxu%lZpXQiaIv+mzsD}1O+Vq!!5=(@0&s%asY`|^mb%9N$(p4o%?8ezL#p|B$ zAxqcptIu7}lGZ)H7lF!r>4i6H%90Im%zB~Oet}UiPFnnWDpEl#-TjdzzrGz*-r>|f z&Q-d4xgVje@UhH709Iw9r?n*6Z%!^x){XVxTfR?zZeQ@5<)xQ%o+S^~GrM8C&RI-WaO%c`$@be^13OT zc;a_AWg$Y$4yx*UHgYfv-(v#fRmj==)WHQOMuLvs^_`^0Pj;aAqbOCRfU))+)B6xD zPA7%i$Z1tGv}{sYhA%7kMp|JoX=0g-$68W{-HxFL2kBd@Xcuq?>7SFdQ9`vV`u`~r z2-|B!W;>*SV4&9PvQ;bm`qK>?URiP;7b&J9ag-!UaVx8X?l<68yo{hz9$1OOY;0gW z>NPP$F%pLHTn`s1%0;jV_M z1|jdCN*@6iU_HPwEeoS$gVfOVhQivs@hmaU>(YX!%$Dn!>cKwkbJ{^#=;a;4m$DF? zjU7Xu+|Jseq`p`~*r7Ijcq&~qcAIMI&i6bNZ*hMa-y8Ow#y9K>+nbRmM?V|K{{$0kpGy)}o~&&X+@JVvo&G%pEP zja_4Nuy}UXS8M_+e2HT~jV0nQq5S3&oz283ZPz(vu6>^q_i#?c^@|1R`&Qx4zOv%4 z-AS5HziR6mm#ERF5M)wJNePipt!h3?u6-l4IV?$_*nh4+{Va4rB0uP?A1C2?j|+y1 zYH{Z@4CUDA@CY`6u+pQ9q9q@J(Nb{FIj`KGR~p7kNz^f1?7Cf~J0QH1L3Yi_aFwxS zrSWSJi?5LzWPXEw?lQ|(M~090TfXar%9jrZmQhdNIx~;@8u1 z#_DaGkp1+GS5V|VRm?POJBqE0n>wL`5|eAB22#2njyCKFv2}%dvu>47t?SXCkIckf zFLmbwKzd6Hp;3$#dm*fq%6J8+S^bO!MIKnQ9*v`Hvv03o?plF?t z;`GfMY|Mnr78=3#$(LJjTUK{)zK31}`Kf{KRx|Qp!+jsKz6PQ#?VkN6jUqSp^v(vcXZB>SbCQm$l zqyUXjU>qB|#Md-_CvM@+FXS6EAJM{Ya^*zArNbzp;vp++jRQh)U3C`X28LDfj+ibN z?UQNz$%$;m>fOELz-!VU`DC_t9(IQ4fIn0)aV3AE*!Sr!a=hL4#(1}J#JSdn9+?HJ zqP-c3nB_+bzEDTiK7?Ura7gKKZv1yr;}5V`84@b;FJj^8JZdtDoNE|-gzH7ISNwbq{e1`l^bSNXx^TCR<|rq$RJ zYB$KirgfCbxmfVf(2OtPdjkbAKQnpE9X&1Z$bIXX>yBPvlpz!KG{azA@gq_F+CG zSKO_M5w|i6-wzR}jh=CMG1Ip-qLr2o=f+nh2Ynb@8Rf=T;;sf0Y|KMeVHCpzAGe%O zKBoQJeIt@d>qUlYloI)dOmEmzwshQBg1iimW@?)b-&f9mDP+ATEq(eTt>tY96%~c6 zGMT9-U5wkeF1)q9wYEZ|-J_4{*=0dV3P|hqQ|rqKW@wOW+Ki$1s-FtkuN$^+oXe!@ zmb(cR#d#6-e5+ThwM5U+7p zy>a1U7B(%UO+q0={Pd&>F4-;#(NOi~!?!5GOMzHe#@o5yL>re|K8GcFOWz`^wOsC# z>D5ttTPV$>CHwYP1*cpol@LH~-sy3PCrM_Z{3Q$To-z-hNpx-1vBuODbWm5&$=6sP zTA|}pjj*Ve8Et`EBP`%5kb((U)ppryec=HD8&c!tM@-_+%0*M9PCvSWx~G81f+80^ zYtN=<4T>3&G_jZPm#*~5-~+Q|iVR_zcf4H}XC%8E&x1!BL)WXFWY2JD8Wfm6rA4)@b=dP20Sv*Hl7s%yVGpn zpPsMR{R&ge#~jyoO%pJu^jEMKTttNq=sjrfGl)M+YQRYQmC7MbxOr*ckv4x*v2}8n z;OWQ2VLUF?{SnH;EWlKsQ;ZI4BwUite=O^MPTS%D#VZCyl!~!7uCZ~yvm0}oH+1q7 zrSnOjBeSHIr_RX$=6>gPbm^{(_O6>k-70Hd3uFsZXVmuRdw;iy+%mf`O{0Gam6hoZ z4h$J}C4#6hDX3ldCrc6>L zc78aUZ;Lgl-N}Fx4m2HWW3aN#;*!Iu3k*8R6CLEfN2O=DNmEN5$^JN}m*T*kPpwF-vQl zqh57m!n!CEGOp(RD-RhT9OZo%^A@p{K<)nId3XoegVQDGuRRm~WFfyL6CYw5zttMo zJ2zdtE8ppAH!fT(y_lcXHg}U;Ug)o)>$?hwmaXox%KKV#1f}rP`sYnlLoA*3qf&;5 zg~hbAtBlHg3?Wzl{g9V+`oX*n>Z5NpT%v7S@u}H(!Iv^6Xib;sLxt#9v%75Y2h?1C zYjP=|YVRGaD9AT0c}Va%jc(QOP3!I);--$_vRr`uYIE31S_efw(aht0ZeOi%zoq81 zcK0s+!@XCg7Y-qA#3M~x4_`bB9citdtUogDFm;Jnc3Kx!(T_gi28o}lq#^9dYY(B5J;$+mO1(2 z^c?0qTUC!3Jk~xlLM9{F@+Z;a0OCcdz3GxuH0{%#ivEe;8_EO-&=I={tukpE5V-;{>^=Lf|g81~< z5nB@C5$BqUUc$Bs|0jXdfqp%k^wu}GoNXRDrVP0<`P?dUA<3{xb{Dz{V@YbUdmPZ> z`nL9NF|1C&KJVQw2Ll7z9`|rGH(?s-AN}w`0Q{sp7uxHWg3E0_Ah1Ve`KHm9uxLC_ z-LrJ8=8Jpl?z9&9+Mkgl#DT=u`@Lta@Uh3diINQd;Mpeu@yr zvovzCV@m{#DUETXjKY@8d_@bsZU|c%lo^}L=sgx%)?fc_x_*OE`oLSfytPP}7Oq`X z7`c`W9XE)FY!172SLaRXnaE%EM<>)oMo1BM-;6*cE!5rxo{4p6pP-t&Vf^kppGZ(- zq_c`#bOkmuLVcK!FcdqYSFzjv8x+YLYTC@WCit{RI0?&06)4n!Bs@{Tyb`l%bPbwj zS}Th;$w78~LwkNa3TUboyv~1iEw?PfNkw`@^++kcxiMuPaGsf<}6*t1Pn`m#Ho7ISf2k8oO z^TN|W5~l8<`xT~ZqG>o5Is32y-wyWIsbR&egOHbe`k5h={Vg?5I!c6ZG}l<`g|_lL z_lr9FG!}mhaVa?&AZ=k7;*z0C3y$~jxH3ovwt1OfBu~!xE{ie1RH3_s9cbBt3T8Ws z7M{Uf@Z0IQbee-d76CUG9X#|l6>0AlfD*d~{dtzhVb-}mt*QQuwi+&UOnw@E)EDo}>zdR6$Wy{$9)GOnm^ zyuJHoiik?Sfm+=@X6s{;$J#A1nAWN1HOt54eTIoCx^K zxD(8GUFyhEB`D9e%?9x*4?GU-vnj+CpTkZ3UUuwmaGd0Y34Ps8O*!dN8Lj;&^2~nx zrdzK49&w-Op0i&?$!%(`@_N@=f8=n#fN9be&7c#J8=y!Y`}=F~!W}p&v7#&? zS%PWWV(qQip5%7m>gTQ)#AgZ74sLVb>7XF@A$cG?_-w9hSR?g1RyGozvmTnvk2*H+ zIsz5}(o!NZqB%O+DSHM>{|$QYaL-O2HN9oOB$Z~*uVIj1{cd<(Q9^UAWZ6m+k}$cz z+<*O(!RAc}NWgSV+B9%}U1Z^{VF%(S2t`%Ln+1;MdW0|FJ{>oZN@jPLgv9zEJ>DMG zZs6qBgH+#^2mSKFl%U0@;vX0bsj{K6g-EYVD2+>Lelt2b`ARjsY zDfP7DFY4%t)cE>W_X9Ku^LAOj$tT+lB`!bUln_zcm3I6zpEe22ykIxzsy5i{kc0Bv z*(BEp87MyvfXl&GudRj!_n3mtA7W_s(t&tNW_8E0)j}`ElzH*c?o{z5}%ZyIPk&c9BES}PvjWp8UOR5b?yL4WB{~z^i zza))fJqVY&BPlZ!ctZCju;Pm`Q_6D2@`y~buYHK+klUI^jtQ5Ymb13EW;ZQEZy0d)&<*sEF`3-DQ$%B)qq@d zNaSzFeJ;gx<;bP_YZEpm;&mLNq{H5%2|SBbSa%YY5(X%!I&pxD?5{zQiqj~jGB%y1 zB#bfel3lM|8nn=w>=-VwgmTttPp)d3Tqs{MW7qp%#4aSVZ_{<(Q%B~~18 zkKzFQq?Qczt>sWzX+HY>+j7JSK4{i8y@d5%KY48u{FNsVo&t1*y-W zzv0~C+jY(o3+#IY#~GjV4^Fhanf%Fqik5@g4AKVGW68sFCuTb84a)+RKltt*bCvXd zh4a+Z>ON*0_*Vkot}6zKB}Kqo!CW` z2(s?%<}jY>?hGO1sL7{}Ria>pqb(onbFddpf<*wvb!7M2{=-DX6#1XL766!c-%mSp)cJT+OUE!6v^Xt|;+NqyapQ1_a{F^+>14*|70oOmjAOYcVDvE(^ z=cWi;rlT|xq>&mmtHH?z@a#O|DS3j(>_O?#bs$`DxnXP_|S*n&>1WMoB*Q;Pqr=rH>NEUqv%0n*oY-$67fyPa#Q;m$+6~SCY?K`#|GSB~V zzuU}BW~!A)*dgD`O6X#G6WrnO=bN~rw_)4&ExaRC6ww_lU;tfYRjp9p{be$t?@Phv zIo>(30lARi?e}Hz>D9xoSOIg>L|?gHg1XCtesrU*>vq{UkLgawa;o9t(Iu+SCC(%s zbn%njn~9)E58B^2a>@al_bEbmmTBaoXBCX2Fnf4!!P$og^!q-{(K@~?OvfDaBOD}E z2kdp{jL|P=ZXsQtyXH4FYU($>m=Gx4*J49C#PIDQ#Mqf_%`t?bB{y~v3S}zTGn6@q zH~wAQL;}vz1VK&SS;O#DY;iF<$_zy+la_j@mcV*!RxiIO27LfqggA`IfNdvjQU-p(@guH=u0>G}M#gY*{@7nd$} zYE@by`dBFx_p37#og7R09%9>V%BUP+QZj6r#h6P8q)`|xDJcDc!J{WRHtV~ z#n)>%YIE3w_BXiKy5VPHJp)CrcDJ~(J)&fGv^kC0_scjV%3b-I**xW&&@yahKXG!= zE$SDcS?g^_8D*x?a%afzWLn!dJ#2MaU^<=CI_-o&aB$LrknVLimkyz|L$G6qR7+kd z$tFkPR30zIat@JP@-dWPr}vq=Aqf}X@~iY78o!xq!Hqjyb&gRE@ASvbi4`j0t`KRV z4<{L*xHm5roT*+(xE_FMTPZ2kQ694DrLGw8i75rW=F8tdFpX%deutLf^B-2`^<2u0 zKl?On|1zGxuAVt_vodU;$SMksXFkS;S6!HxOB1-a*h?%K!r?0GbWECvDa<{IJN2k_^$P-#LHgqh z@(Hkv3*1=?Fye4zbP;Eqz`+!nu^({c7$|nV^;0*Xq!1XIAbe^@U9kh{ zVXZ)T7;u>v@A)n`^O*L~#>8oc`HiPx;a$f9j<*&~xx$)dQe>L3fCtF(IOq&}A2L=3 z7|5$?u-5kTn#zwXQFtffG9}TkU)^uI`j4@I&snm}4wtYuxk}gva?w?KJ_|(0;@>L| z1>pB7hi(``li|M56^Ewu4M8uS!|T&jtGtR)!qz*ofl5>saRKn@!;2m$73&6_O>Jj&|7xO68VP~O8sI?W2E1W zo^cU*z&p_y?p^L-9Xa41zP0xO@(Ank!bO=Pg3!w@GcUe7zR5AUv2z zO_u)SjTZoUxI$CoL8!6RgBu#zWSg5G(6>+$8pf&+R^QneJPF!nWo}>|v0}A;t7r@{Afa@HJZNQhqp- zlG37i_fSE*w_-HfIu`L!b$lYYC6*;MX^1brGF$eEeW;vpDa|ieX`^+?IIY<4@+X#? z)|M{1|DXl!Iw#mNSJZW|-j#F%bxnDJ&J1qX`A0eMvl5Pmy@*|G!l*D}F=OpTb4<3Z zxhqWb>1yG(I0|m*VS8FQ1XeJ=cW7~Z`l9fmc)c4#pQfKOW;ecvNd#3ddJ=fL9pAut zs-2V#b2Tt4#bY(yXF^QW9Oi067nX%Ks#O%QPu*^8J3Gxp@Px*aWh znt@qX>fBZ*m%37$EX{koZX{_CGipp-;76G=W!K=0GUGQ8__UJzi*QSI$I(@qI)c74kfTAIFqt1 zcD^G8)BKo`nXA$x;#|Pd?$Zd%s8DKTA(tIwl)$|Oa-cfhzZo-cDBCv3Jcz=w5{~K1 z>4q#^rz#*QLT`n5RdNrPVN;qa!ujoB+*9Q=Pj3;{ ze~`vzsy4FQa2V|QD6Ji9b2LtjfcKfuPVRRZv}Rd-3aWHxFTecSb1TdL_RO9xRC)QI zY?$BlH&g2LV2`2^i1X5*2B{zW{6@tM^Sg)UJOjp?6v`)V(_C-HE)Fk^Es}0+-5j4J zlcIjKnVmvIBPN0$PgGDUIuX~T3pc$50FYbGATCaX&}w@m2N%bB43`G5mE*B?iL6Ck z%<(+K)Mu;x3MHK#{7ll$%4(|P`*59p&z*)*if2lb^n6Pbw!G15aovbqm_UTYF;Zt(=N;f+V z8nW{XWCM**e`w}$Sn+EGY)IqdlE{Pk5zPBXs^^bj$R4_&DjNUMQ06{t)Mb#9M^|#V<*Y08H1ofesIiV-i8#iM8Ewx1__gp59~?3FrxqyC9@a zkE6U_t0Ui^a50GnywQBPs6qV94vPM~A%n030oq2+6Chvu9AIAARSaVOMNW?rQ>@-} zNf|dQ8GFS$xy7|=*|+|psy8jxhVLsv*sE_8T%4sO2hDgob|+S+ZYOU-u{u&nDhz@& zM0bnuNrrXCiG=~AQ+T}6Y?Rx;QIGrn5^ERa_GJ1xYN=%KO#int?l*R8>OYixa+QGW zKROYlEvR|4p1TNhk-?461-DJ9BNsR&1EQnVa?xVh#;{NHhZQvDGn}*{mQw)8@Q(Z) zO8Gg76Kx0^;nyd*_}#r*m8OeIs2ur2b+2FP2D%vv!R6P5 zYG;b16zy(SSK>0bh;!JqPs)&{CQ>Ww*r=rQIXkLj=T?fJ@t3`*_4kV3b$L8*V(cdX z=@d)$ME0^@=5yNz9u2XB5lO-Qys9q|2kI>=rZ4tnG3(9R2AjrIwG1a#im&cDz`+oK zMV6UI!t>*+JPQ{19_EyvJgQuG%r-m|^KoYWF(8 zwZ*KU*~{$>r@#pJbRcC(dbE#U=-n?V=Hj8e_X4q6z+0W+=oqilJgQfUTU5pDL=TAt z*--}@5W0-c{16{%`Y}X{7e^Ce)d;H6l|zf1C0P!kNE6c}S)_{jDp^S26k#8*Cs)~|8C z6hG?Vee8YKh^q`ie|ZTf&tR2s&OEAQq*+sC2T!wOqf39OS~i?0iVGqlTG-$9=9=A^ zbpAqA;D}@q3Nst|Zm6~m^wenSfy{_!8<0(z)TNEgwnc&L^25YHOml5t?)h1!W z>`KIaqLH#M%P0t`q%@6 zY{udK+|`Dck>cN=>v=xDekd26Y>!^TyBWlbtKzH#g$jJlk7}`dJCVH;vSP=^MVaI+$Wo&)##G4!B z4^=t?KdCfFOUzmT%~Am=@qSr&7W=J)q^cot!vYs;PP9Z7j|&P-rWq#m>NLJ0P)XoC}i2jK_6z(?IJzr z(C>qyn7!y(SKNDv18{kK4Qr0sHG(QT7F~>}Yukmbck?uZ)p@P#oiVV<4=+T|RcRyL zrM?Mog^5gz`k)x&)0O!lXXiPU>O=7?re#psJF~hr&?Y0oHFTcCymF0U4^o~sKN+r< zWv_Fo4vp5*99rtmDIB8fdbFl9(3lda(VJj-_oDz8O#%Xn=VN>zc4q_sDvQWn#5u;s ze6*V%BP-+(ngirFQ8hl7&C738r@h>VqW#g6&zT{*;26(2g{6Y0`jkd4rIN?gKuY8e zxJc0V8v#GzHRn&tfB0Zs&9SQI6?QTrUb9skA5`9)n3uwuZ{`W*Gl>7iItsopSA>uh z{1q(j8`~q~)Btz5HOv5Vb)EyTusz12VaysriKiAP`_-2OU=W3=#yf2;1u%0buG^KvQ1 zJ1Bmw&#zSK(pwyTTvMBu7s%rTbpPFdb~&ZKTaf~Qu4gKBxqVJKZ}}nA!|O!6@NA~5 zX*R>C|IQl7>f8NyoijEA?!+qw5R(pRYceq1%Z+>&R+6T80oV7!TzWPUJ|v`mm+LCk zDeDmO@)`i`h(6+G==a{NEgkgnad#K63fcll#XSI{setkZP%HqbxSlcPev5yDu?wVI#`wHYiHqZLSeXV{t(3Jsw;@3p1A!i(= z$OJ4o%u4`F?CZ||!SEvBrFmR-z#X4c@@o4^cr%PAsrH{0ZhZaVZ;KgI90R5cdIz<* zi;hkKkIK+ds6)zthn(Z~`mLDi9FY;{szQXQju%d8<(LQsP@_f++#hmC}Kk2#dwGe02Seo`4YMM1PZIi zm6d;BxzInBxnW z(R!GR_GWy)x;g9~j;$oClUhl!DY|AY92^FE^gx)71QFFMa77%Z2Jr$wu};5*ZMQTK z5LlOr4D$7hNZldd9#=6>A{Fgm-!~&n$kiP2Jr|>WzYelt|H(aJzqp9l|?i#K;OS|(qQ$c=&&eapq z5J0$zT5Lq-7O73ajQGBHRoi3|9gGf^s)of+(egu%2XsY{^tTN{euHV`_DWaY%65K-wPq9 zTU_oeBz0&Z?^3osW8f*64_?58wfT1_(xlN|xKMa=SjRc! z;nOavnpk$nr|;Ji0wt6K7a6dY!y|oZ>N@9sfv}zYZa6CYDn6L>QH-W;+sGoi zE3>yot*Y=(IQLhx_jDG9g>}Czkc$@G(4F}BM$5x@!`Gl-1Qv$0&pLf;SYyRls|Y&8 z+y(VW0g=)W{=HhrHTw#l%nET1=+Z+nb=t9e8c;4&l6uR1SmsPRJcll1$8Ty-C4I?? zibW+d-6>&@)zE>eAH20QK5ZSbv6IXi6gj9?nZ;+!)g%J!9ylr3Lut&2Nlu{+tn{b^Gotd zB`3pwIxJIQ3=TjU9AgKqcTg;aUEh`->~+Ci;ktIf;d%v{?t;8TxQd7zJHw??Vb1S= zMjNjBCeuSP(tn77LI;4|4_5g_>BQQ_2i)QV=zHFO_is?>FtiXpv+kzesl!I8MPUD5 zgTc7z&1wkc`uG#TT?&y_T5VSH3!W!8Va~|M-@{i11o-m~;KSDt;To#=d$jofDNu50 z(v`6DV5PRuPlb(6XuI&KA|c;EL1d>TLuQos%Ighu|TMN~;=_DSN{H>ZUMX;eo~ zIA#}X7;mW?4gjK?A4ivcg_`~q`!IMpCciCY4#k?Q=U^t2WzCnON+s4p^eX1mY8+GR z#0i;KkEso?n>8^fsImFl)`D9@$Ss4X`jtkB>@G2WUI8#FMWOSe8g8-IqK8qsYibz3 z+HqIX`P4A}e!gCUExlT|qk&tf21UC^<7Cc0^qfc?% zmdy!yrf&gQ@#c_eM1=yQvCKm`tREFH;2PF|MNgEIg9qm(83z4HT*Tw^4L176(hye9 zbJ3Ve*9>-mMZ&n{BLGQ1qSy(tgh9r#i;FC+YEFo66E`pM@{2A=XO9y1fuzTUo{@PX zS~;=&!O#s#reiOLsflf$oH)!z#v722(4iZ}J!N&*?tayFL_bDsBK! zxsxHZ&>lmYni-LiV+>Jnmk6v%RYJ&8L&$3>8)lS$N4Ox6%&98clo*HpazO@;B5(D@ zM%8jrl3tV$vMvr?-x51^+i!KW`vBv++|J~lJpm2-?ss|#sGunmuS?N_GNbvq3>>ZI zJu2v{m@X#xBB*WR7k8QB*cZ?}sv(n-MN7CZv1I~N5Ri>Tx3@=#IH5TS3iY_PGBPL* z8pOLTEzC`|i=gREoO}e9^^r5LKIIgxh2T1SmnmMh_>4Nz&ijEn*dv{cK_zd{^Q;r{ z8O!qNF=Mx)I~!nLA>4B?TsSrLQO-EPES{0}-AR9GEu9|mjb3f?kGuA$a{4`Bxzy1M zoY)?VD8E9N*vXXlc6Rbq{KYJxp$qxtQT{`AdY&+ikCwkJ5O0humM!Qxa1d~ebXH1H zMkHGH2#mF@Sj>8Y9pWne*Yh-{AI+GenBC|;bjZnIL6M29|KV_r?doZU)OTEB68P){ z9_NrDAqze@mxoL8nPJY0@Vz#SfX6iPw<`%_J>SRr>v?$);Lh)j_@E0_0nEvkPP4Ih zuQBO@5%ANX3xbPH|O$mmf zg~t$_Z+9iPzY#p&muMl>Seu@wuCfr2u2XhDP1|;`{m3Iyl!PzB49yZ>plpsfLZ!FL zVw{(3SiN_p50b1=!cFw%PbkdYR+O$!J*t61Xwy)k59wYo!CWdy9bcMwl80Tt)T)38 zRc~i4g-(_WoMWnAUYv1Vn!%;d^=wK+Gz}}R4>-xCWU**T#F9&S(yTCRyIL@f`W zr0g?F#V%O)^DP07)38b%UQ?x2?~~0a5xPXK$p|hE7u?)7e1>myEcBD~o#H6bvBE`U zZm?ow{dDWgOW*r7)ZA=M2aBYqUj&~Eze*0WKB{N$&o?*r#9COgx#4c-m&jvVWO`b5 zP82!nWqec4FGAlVdZ?DzxloJSIQdcVFPsYu@@2dH6GeL73$&i62}Ays15;HqOEGT; zH}q4!rT)=Q4P3aG-RH28%a;Lb__k9w8CC9Q$yFC6aQ=szTU|+5ms26+q~)oZgnZ#& z9DPLk=$QiubhxL>$1B3_MbkaD>Y;A3NyREz+dz-Ug>YSCKYVBb-v@S3A0L_Tr6#FO z;C|{y1GW5uL*yg2!UFVrIumahsjA_U+L6On(%B@<>bM z3`Spwb0?e|9yb}%A7y2MMgcCf{ucNBY1}1MOj9`58oAl!iZ%K^u)B0bU;F^($WpCH zfz-G1r?-AbSb2ol?Ym4dh^MPAD)VK|v@|tgT~x4_!vy@}r&~+tv_ROY(b3A>4M?f! zB8jjGYq`eTHH>$`G*UgPWTCWtFF9s!%ia)o25y*RV}DC|Z?|3&(cVmbE2*&RLA^^o zV;7Y&npAyqkmTT5tk+2A*82ZmTy0;l#RY0J6yk!y=;HGDcJ2X^lG@?o$18X#G4Bs2 z_<+9JHQ8_U@bBXjTf)yFAWfJ@xQ~c(NBiC?DY1Y}-bas$Y&R0T$D+MS^Lm;uNjf-2 zDyEpk7gOS&sJ`@}H&2{S-*Vc{p#9J#x7sZ&ZY=Ix_Zs#I>6{Giqu#%`s4cpEiUOti z1yX3SgB8WXAl2%2(|lTgn-c#_wLB^{P;ZP}NQ_-{!U{NgxCEG1?kSHt%L*W0HXI+Q7|JEiQrztF z(Od6GSB(+cvWVnnl5o(a6UZ`^f$FOaK$O@0PV->17=;Lm3&NVKnUg<};r1P4@KbhC z;t*llusJ3-AYE77BeSL2yy|#{E@&fpgJN6NPSOxjR zhEVTHRy|ojFPd=cD8Vv9ig>kx%g3xpJ;Kwiiz6vFo^?H^1m4E7>@Vpi_&)ievi5?Kl^#1TCkf89b)|C> zI0}phxaF5C8ovf?lhwzp<#Gt?d!(p6P{%pAf*15&uIl9%`0YK^qQj5?v&*ZU3XU`W z>71w276{hEe;N!A&xh?4eXsZyhf#R_()jPe;LuxY5@)%bT{4{?j2Ga#udEd=2>1Py zWDmuakQ3L_JW=*S?^4P;l}w!Q3?fU02{*M}!BQvx?AinMo~*HC41K02rX8E39~n)) zj$h)^{6Dxvqdz0WX51IqARlS~YEft9c|Q{J)ntIHt0>l{p$C<-9+k(rJHP86us_<0 zk(p0_Jnez0x6I+n7Nkcjd^0TJSfuNz8IetJEIi5fVCirc-b}o=yCFr;+FKDFRll@OCV?X5!JZq#U@T4=Zk8` zm#F32iB$&}_&JW;+pQuKJ62MUzu)!eL0fQF&yroE-F#tUr(ATuf>F*23P5w4NPlKJ zFfWCW5ey~kwsh->IUItKfDMc~A0ABxMH4Q6w8EIeM~?QhqBt4Q!!qbL*Nz4euk?T9 zOE51dede%X521on((xZ#{o~xiwy-;1P8~~!=+<|+2+?4L&3DmhFVA$vD))iorz-(( zh4OXX&0pA4J`@ujeFH9lyiS*qdLwc{2^KbNvy$n7tkb4{OpVLlbswWKKk8c+53HUK z^!mw|uM)HxK#k2NK}A7u?Of2T9t zv8EM3_txak9&I1rt6ajO`zr7fE1hi7BAdg$E$V4qRwy=wLu$%Egpw5zksMowbDOy| zU$!`KtGESmHbT$amxiDG-mUXA2LYJdlCxm+x;Adk9xW~>7i~He98B8 zl?7G^4kjDG(yI9R-N4HfY*}8~E5tgN_VkilIUHT5|M#bJBYmm%%E|3IC@5L}$EZK4 zS-(~GyGL=1TkMND!dY&8ephR$#?B8#UEtiUfIr}v87tb`Lb3Ca9%CeVq+FcN~ zjNoco)0o>&6ga(gx{j@8|}2l!g@XNh0ew}Q76jDe%g-xgULk4qMCcj?bN>TQKU z0t#ve_A#DL9b+I>|1rIHbVofkuXSc zR0n?#N$aiMY7hnOq4%4jw(k)jhp4j8hRAw`{3+INQy$YT4$C(ED(14z`CmH%*YSwo z?_ku`-vWp1e0>0sW3_oa*p8XQ)E{PUhkW{Jr0aJb500@JIJ(A&eFuvBP0- zt{&Gs$BPH--~iWwfR}%)I1s6bziogQsGo4lli~{8uIrThlF#4YQ=21?pvIQgO(=o4 zvm^;KRLqG2{h|=_dw-iZ@P0`qT>bmG2Otglp&3vle8)@SLZa8zO3*HRd@5KTguA8# zviE|l-f#9CoLigO57!m}kKf#5*Xt)$`;xL2Lf7hS7E7t-)!;P*f2{5SMDwWa-G91L zA%nl|8lXLz`dgz$>!+Kdgv7{O<5KlgY;$CKt^!&>$rMZCoL8A~7M`oBq|5C<_uR5* zC~~1@%TCn2BUStY%)l7>Y|T*v9Q2PhZw|BHe;;E!9^Q37%1n!Q!F3{zpa7MFNTk=v zMF-&4RO%nr?g{%>{mrb}H&vcqs;PUQ(7Qu61FPR*f_r1J$Lx^bbPgkb@S^gC1DWH~o4!n`=|Spsa@;2E3t!cn@ZjHCKZK&R{)g8ZjzPT($7O?52ri7?*nJ_d05zA6-KD zHKFFZUNoK`*HH1Xnr+S3fw#AQzCob%uw6Phw>sr<1Uj-u3CmvA>m-9JQ@an7=n$nv zsaTlwtCnlo6@F{~cJstZ`>5kIS8eC3xiIG=D7X9^3Z*y?;~{}3yX8{g%lSm1jH#uF z{T^r;lH=gSnu5FE$^IWV?5A<9bq)4q*a#JAw?#QW7CwQtf29!a&A78(Dd`kn8-7?v z7Ve+EWq8xG0gxetAyi2&*01!I^R3?owW8Pp9*j z`a3$T^#oZidAzoeVFHsFeHZTH%Hv^hbAv?02~=^f{XmW6f%2BvjYtT($JeYTw7>FB zoseW0kKuPataMn?37c!-@p4vGHNwcnDhS1Q>~g#1D@@KrcZ+|W_h1Ol9s2AS)i17g z!tQt8ajU*}K<(Qd4fUpUZJ`Xi?7WEjr7!%Ns+;cJFF#!`(qOG^(Ah4N9pAwlsu%=i ze+J#PBf_nnY7SclpOkq(KcC{;P~)>;msW#e`?My*@vbEX@h@(M*bxI18*f+H$uLZU({#~k$szr^N6|`uJ(2qnW7(A5w{NX z-Oq{cfE?$(F-9b8Pu-~OJ=zoBv69*wak_E4FhMBPKP z?ls?ZSH(b0pf-x(o5a!eZ6+yWRIvHfNqe&r!n-ShHl3Dzq^rS|dr6?M=Jj5j<9oK0 zytnoto$~nNuU3fsZk1hXb4zPJ@lU8WEAY=qBL-TioI2W)>3t3x7H;MS3mBMt{Jq_#r#7l*6=}F z)OOiNueX=(oAL(zV?R7Qh&fJYw4i^F1#(cu`@+Yqxe`FgebzuyLw$Hs#d$VP z>~e`?>tzUomJ1?yU(o97ah^x4!H*8gK3(iX)Y!YLE;@DmQoklG1bcyMz4 zUrq^wJ`yQNkDY}%+RW{J;vfb?t^TCYLmFDVbyZxxGWQu&X<^-6*;8*$&Yc*7IR{=B zhE9;rm&BJvz;`tg>kEoK+|TsbU_p8b`jn1`01J2<2`8dTb7bP(%njl}Dp9DCpetk$ zf873uZzPlril6=Qk|$Er#23E=ZVZo_9{ZOT;rLfe1%lnOx)=>zpJq1iU8(kIXR*|p zApM!^q6=E>&j99?V|O5ErH2qK98zzkBufFj0Vu( zZuotfq<-DS$R9Izz1ufEc6*i#&P3>6FI{;h4*qK;9MTlWGEM7m!l&w+3;#AlRPA*! zNRm0}cGLGxX|^T0%A>6$$FJ4;(9n51J&!r@w{Es&2S`VACsGJSR+gRU4r*y?nhi09n1+O&JLylC8`~;@m%021o8Rp8 zXSb-TKH5chFeWm(1-r2WZ~07U1s|NuY_9W>_j@kHoo;qYSrC5_(kc^V&8v#GYa7n4 zOD`!;y~-nAka~&dJoOUc`G=Pq6G?NH9G5r|v{O%e*`|wp`;xp_aw|ze*2vIK-MRoQ-=S{BgQpD?@ zN&!XJw4HnqbAJesK+Qx^qx(NBTt3I~cEWV4Q?p>L+1U%qAshw3+hFzdx3Jgc&pPHO zLAX(|TU}~moGD1Q!QtUT*t|Z+mn$K)bx)6BQa+|y8Kio#UNXWI?i|Ej;jAhxmE)fz zz0PPb*GnsLjOx^g@I>-UkaZTYBMAMU{^T$*zK@fgK;4!JPp zd07xtRYK`7P7MoOz&>Z=A()U`e2RQrNH0PDk`B}QerCY%2c>OY`%jUgSibSb9P_KU zINPF;G{&e|-TsYFEPTUxNl`*re0+G(g3d%%VdNHMD8_!DWqt7xR8)@y-PgKo5uBXu z;V}|(2Eqz1#t}Dvudu(A9Uh4@NjKEiOB=VFc04`cjwgIhv(vq-B#{<-0ME$Pq@!Cn z?`a@X9@z3RrP5%G|5AhY3^H!7OHcN_0m9YUD9&b=N7MMNzOM$#uzOr){>05J;xRw1S!JvA2Vd3pxm^7*jK6eUC zEcnjjKhFCkcopLcc^72Q*ojDx!(1AC4RCq-NjY1KK=nxW&Y5!CSq}%1#7`)+Dravl zqm==gxcdn1x!nmVWlO_LF-Z*<}KJxqrx; zM85gd#*{E*^m@Lr;9?gWm>;_?6K z!8zQA7KgGyXas5=mYdd_az0oNI9H+rPTv!MQbU7a3?OEx(`7aQdT_bWI4V(^{s>82 z*5VqYd@GqF^6Uu#vBrtV{pFW{XCyG1VyG$EE`qFOv>0{>)yr|roo#OzZebDI9*O(y zM!D_yjar24LLQ2cE#uOVXFXIeOPTE1bGFbMDgRdB<;PTQw}_dMzrrX{ruwAb3Y$SY zf$$tmbB}Dd!e^xdn@G_dQZ&r)bw@$#j*;;B1=qIWJRM<%L!msHX^;VE9iEy<9ty2J zQvQ6H2&lU%170s84?TzSmQbiB_VK|v7Wi>t!HPV*{6oipZ@H4yZoCxD*UgV^VAH%s zT-8$KO=Xz>F=VVT)GVCx-|f9CzqP#PrlRu4^o77q_MS>puJD*XjT}bJ8tfF^p@kv^ z?EI05;}e-o14HzMJ1Rdtk_!)IJ>I>?tj1U+sKgS6*r0ET$*m2$Y z{*mG_?j0f*j{6Ko2e&ZwEWQ^#o!(x^j%t!`dhy;6_wC*!t}3fr(bVQti2*l|3m7o( zA;xnfCf-RZ6PhfZN0Zw!3Sv42`KFtUBZE8dqsKB0Iu{`tt6Aub73p5L3CA@t(_F zoxTY*0@iziGKQfw=_bo6SkVJQ@6+??{@tJ=EOajj>lYnB;9!G@AFfWrOU#Gys7Kt= zvNO@gS{vz-YBn~?+)?F3XVhd*$TtWWb;20Fjsdlcoi7SxH-s<>Ryh76>cRqFOpmAp zhp)wW00RA0DFHFl_h4`?ySKjFdP(SuyOwGZ79VF3zFCA)6NY8?@8?+;rmzGE>?+{u zr+^#Kei)wscJt}?1=xG2XKhT8G0nR!t_p7V5#dvE%Loo&V2XwJs6OU6t+TO)WB_^0 zf2@H7gqlt_Jv3d0u+A-lq65*|o8Jjn6wpA9$L$|qSAvS5Rk+`Sb3b5foo#B(Ug@_r}QSD@|1l%St<^*Ywz{Jn)HUvoOl3H(>Z;t zcF3^B{b}0B33AulLM1EjnntPdJgs3fOHBb5fr;Sq>>-)k%K#t1yEP67G6NJ*X%R&P z;NbFb-Z&7*vZ*d>e{yUo!v>3B1k=7hE6y@)+Ipof4$iarDb}r&+g+27v1=j=tM;gT zz(_ErE#u{%Uj$_;ua_Xbop#>mX6$y!ASZix5#_RR=O`!^)F7_4At%{x^(2%n2MCM$ znGsKag%1A#2{F|U~6_1G2fk?bO0Z>HfiQ#}}sY{$|p4H8!n3m*S z4YrBjMFuN*pa&yQ05LS~KJJRxa5QZ{B1CpVWe!kW)%BFe(y;GQ*1r$YfKo?KAZGz_pOz?u zW`fWi-xstk8imuWaFG!&F;axx%!>ixmF1(w$y32(X?|lmD>!Sn#sgW&_pB6x4+=ip z?BRV0W>T~BkX5A|lHX>!JvfGN(*)$0YAn00KETIbO^85Kb^c;($0MlV0ks3Rr~jjKM?KF2=+Z)os%(R84k!A z4BNi#YQc3V4Kp67Cg>1{#59#!FdS4*S$b$%>9EO$Ij5gnUOKAAM)Q>Dxzz;~SSsOr{PlrRl(tH>Uh@zy8cXj;A|$ zNQ~0CqO4)piocw&CzRK>f-L#m?z+PWONaOA%0RsI)u`g?E81(4AHUQ`90!SgA)zS; zkO6uY@f4DPZVia3Y#p5wJu4tN1z;XYwB|mBYb7k(Khu>_cJ5$NKfvXGqadAM*AzC?H4`W;fO9F-GMHEXdQVoUfsBhn{^+EpxPkNgd-LuV9utv~G)sTB$L9$m z!iz|Ms^ED+nyPnNsUYTRlLPBYGGsZDgwnV>LqQ2tj131o#NG6QvO4~-%Ke744?{pr zMJnvX?=^J?i$c(mmQKg-?0FNZ;Q7KZ#HryAC1v65W1&%<3^MeRG}!Rlmc@K6lt~jh zxfPWaE7n9T9H9K-8TFk!;@>_A?%ajrAr>Uhk1)q(WGK zf)p2!p8^k8#=PRlI}>v%Dvf>HRgAH6dN21fuxw=8<{RmVJ(2;`3Cj+OMu`gsN-C=a z1Bx;ymvnCjP3kYuYqk6IqMd0AJowysgzGmhpdh!+pK~9`?tu*Pp=GXSusAT#KtO?m zw<$<*;m4rqWu>Y~HjNSeY4@l)Nky_Vs>LeRL#eh_6W35Q@}^f(aR`9Zd)8#Q*tT8R z^%=0^eQzmFYjBeI`L{mAPmc!UjNU&y(B6mA3QpzpNBTb1OypK8%LUn2v-)naPTu4r zK_-e>!>8bS)6cDgjE#^Q_fm)8tGpsLVb-mmVQO<+)o;Bu25@xf8!(sI~xfP~o z`py}4I9g19opY}le>1A4&;x8bDkQKfKXHsc()f`#^(-IQ#N}WsGVHiZC3x&mgCxOw z`&*Z^PgA=X(dBRZzVoln`4pLZ%WFJzy#2eV@0a&RExmgMO$|5iT};GLA6#}x87G3% zEbb~jTLW3_D#7r{kT|P#(6z7Gia<>VN?ZRTmQLey@_ZIYxjkXnta=-k=o=xmh|ixF z1(fuajI~Tf_H;7IAs7i)!@h?)`!lV%wQ+ zQSvNXoQoQXmBz`mx&9nxyW`S4<62P@T!UDe?Cv$KTr|4Gz|I&at&}6y`&tLn(3JI7s zONY-&I`R+^Xc9;R{}OsK_@1lj!vTN02SBAVEi#~vdk-wMv;uw?YV!a_aNR{nO}UWY zpRzNIXOQ4fIPgd5H+GhZu~ci9T_05BgMcgZj>-kSh6 zr!`dY4-k$c9UotZy55!k48jvjZf}sRyfHmgPhV@~0LcbZoqy07#X-Y_sYNeCagca@ zK^e86HKf?~vAt>UIA$hQc(}Tz>mI*9dPrs?SnF%nLzxmj+IRIS3{6?@R$qO2lme2< zmacs{BSyrLkF(~HB*u$tP6CUh$LDL!rQO00gwXcZW-Gp1O?&w{TLFT>kB(JQ1q|Go zp0dc!aLn}=XQS!``Q`J#$#y2B|5P;o6NqEdC&I#mbmpa+DM>e!@G>qltsNP(Q_j6| zH?uBWGz|VCdV95`##a|gycxB z4U4{h;Ac* zBYJgz#d?T7C)Q(8qdl+ zi(o}wKRXUP#q1%~u7xR*OFi$UH*v!8m7C$9TfxVY)&@^OZ zAa20?F4MAGrDY9GPog_} zCzILe(2tY^v{xVyjVnBL*(PURoIITA*(~6OV54!9Y@I3|;==ylRu?<=SlaQEG z{^uo(^u$o7KKj{0B+!}7x%g1AZ3B-d@--px{ahmlyl%Sh%}|eW2$mGvBtFAeBann; zxJHW7f08;R-pi>5RMe>sbJG%|R&#J5h?9YRBk*QNOo31upa}iyCHL$haF>N zN*ZSQcKqf!p!sz+daqPXtl5dX9NMUs1b$~d!Z|}LOzL=l`2dOaDPf=Pfe)t|v`%irz@Dx_Ck+g?aoCI=A*8p)+xT@C z6tZ9nX4xy+n^X<7b~Io$M>7T#zh|~Yc6Uv-Je+d;E1_m6?|?y*>9X@KBv|3GbL0?y z_oB^SHT={Pa!+{;Q2Ags3m1FD!C;nmm4kV3!)YI4R@Grvxa0VS+p`ClW-kS1)G!=s zn4kkT>P(48rFgBm0pi9LgfayY3)%zh5u5ih)MFNM8P2IV7G^V|6k=;+xwmqZW|~q) zs(ZHHH9;E4S>599HvJ%{2ab?xIcF3aM+!GM?8zH!qIj6lmh<|w4>@`WA5bAtP12>A zrV+Q7IM=F-&?f7c`X(1XGuiKR(jb;xB>rs-EnW68mfvdG+YjbqVLViNF1dGq8j0&` z1E%M7ld1o7JS#e?-3o>_L6%8$DDB??P7CBR*>VxOT*nZML=_;l-?!g?vH^_3iw3eY zIOluPp$qo>)x&z&;XdGb>!Q&VuX}l)#G}0a{OxCN;in8Yz}HT@j+cso#eGu~_dwvm zIxa9Eb&3F{0&Fcd=-?n&vCr;)p4e?rLi**-Ke#8$YgcUz=YAGwk3+Wj)B@kOyb0>lyDwJw%hd zN<-Hlbq>T?iIHsySQiD9XDhJ`(-=PA+0eb*REC(*@C0LMG!C+&VC{$a!%EM3hRqS8 z;jOSW5y;;-DL!mZI4T6NOuZ$s1vVaZg6h0L*y&Fyea`fgruVM9#Hu`jP2gb7T;I=K zUb#MO+H4gujV^wyvRk@Rda-E#UEEnfY(U>S2KX_#g6f9CwI9NI+mICsxGmb_Kxi?7 zQ)Lb+Nc*s`|E*Z%XbcKOY$hH&*RNKx+yP3(vliji^G@SR5Gzfzd^p!d(H$IABNlwO z(#lhluwQ&0>?P=dtj3an^&%WD@jt|J5EYu;cZpF#ed@F#rv!GM&l_$ig|*eH+@H^= zwPilb#5!BRUzEVIVV^#;Xu_cwglMJ5!=27gD-Y58nDA_s)7fydE^)#jgEyvzvkaL! zd96r9-e`<;O;2meL(yWB@c4XYZ#`MsCH)%6iLk(rG=Abx{dJjx1ji~C>7ylLR=V-P zhFPex?7C5m7NiGUVuab%jPx7xRN*_TE_0TVZpS%njtaB3cC~hm??I-yOLqL#5|}T> z^^OW=c?CGnA^Z1&BeftCn`mO(6=(gp%3u?*2B=Ms+WiR=QR!_aoFsyx3 ziG&@^EL`;Xom+NYWcM9H&^_w!PhcV_r9J6~AFX|&HI2jcaC(VhB2!aPZGv+~90`-suZh~cC2|aovtz6YG$BA*X^?hnZH)vHRuCg}# z&8*|>0^(|Bp-Q9dMDa({V{~|9I0YqJ8_QqU6jbj=_O!QcOM1`FJnlgvxSHP-xV@=$ zA}MAlSQU+&y)layCr0zAxVxTILh-PV*NyJZB2|H3% zq%Y{%@w!8l`}oNLuMXIvOwrKb+!nWb`ph$V0}!>o?07Fo=m_jvw}yck-VS5sQE-+u z6BWfQPzHTop31}(^>3*c^M@Xr-ckABSyj%sZappk0?qh);%)4EkHdf0EYx5z89ZAi z+ZpGfAAQ-M$tDh7a<^N@Ihw_!`jjuLtoC2*`{u=jEEHu41uWiW9a1~ACv1LT_%ZCq zA0*qM+TK1~k+F$))q>!xMFgCJ6_Akw{38o<$w^c-d!t!~GVeT5`nF|}VX zd{D5E^E-$?7a1_lMCmCY&o|}LccQ1$aBSQp{DlCmY}#6AiNXgH>S#E<3?vy3fVzUg zB$j<2CnfSga|4 zsPybSzE43Nu`;uARVOGy5v-%84x#Cx)-~2%lNB}Dw1fKioz*anPlFTMNCH)lN z7Ls`vpO^S00bzx?(KfmD7LiS2PP*3li)Hv1$mgWe;6O2l*U#*?=1bsmiz#g&9PobO zJ8q*&@a<886$xnedojZsoG&s99mY+WVo@?A{4)+oFZx<}oR^_6QA10)1u^|RDH=QZ zwiZN$`2({WTJk^dGMUTfs8?qMN=@3Bnf406V&pvS$gWwit&QNjBteyrN9yySLgn0a>r(CZmX{7L0xl z!s%lrXsVV_v$;kKA@hl=nH<+VXi(iS0yJon2!pPR=>_1<#j+jKnJ!)9<*e9Q(2c?A;?$|{ zlj2>HR}IEDP>jvfMRb%aPc+MJi{sbO^CL^CaJmE|zD(kF+WOa;&IKY;C6(pRzW$Ayd_<{^jrs}3v43Y=OM+#okcza`C8Fwd>jMrdM zRm6|4u_HyhJWt+RzY!rPL(auUforwp!Pr>uisCB`Q93cg0LG6lI<& zdAPT)Iz?JNAQ=fU9G5FYrXwFe z)&SjM%)nvv$ZAA)x)V071mc4gtPG@rSa)fYumyUKLaq zpSk&9n|z#M;Xm;-tQ~6Xkufz#7mOp(&T+nZ1?%M;;v);*hpDe_Sm7_+Z zVXnKrevR?6+d?wj?b=3BaAr@}FG2uXOFhvOT$_JzcWPL4M*E%hp#Hy77GsPpK2`L7p$p1ypMX_SlDPVOwpeD0(L zdTXGhQU(XgACRinM?l>Zte9C3A6|{ZMJ8n`e~S+ijDZ8A3r#zfWlY6v`|`$KK3WFm zSF8e5FL=hQxac8O>>b*!G_BhYbC09e9u7*?{nB#BzFwN&m$)5nLh0NVxP zf5pv%WCLLTs03&WjuvRb>FD-?lnO$2iHivh)8SHL>nw@Q#(Rm-!sXhqEGTKWz~RW7lPagCONeb_dI%&G@z zBu_FwkiykT1B{rX4dED(A>4H>>FoVSoAx8prd;j4FNIh&Ok}*2Z_GNc?J(-yaH^+2 z4O#udwzMqSZ9&m0x>G~BcEwEn=Ku$3VC15v|PaNv`;HK3|CQqvz-2N#_Roa>|w6nCF+Y z7avMA4C8ns*)U~gje8jKWBubuuf8Ls5 zaEUFC-2L6J$itgySeOmu44P*~-fw6?8dxqUBTz(Az2Sl{IV)4KYQijhYUJcL52(7w zOwrO$!ve|6iEJUdi^^kTIDdldYiQ??{dKUn(-pw9fMiJ}+-=-KtcPtogQSiu} zS2A{riR*mQEm%!KN{KOPLOSU97xlv76qo&Y`gGsx2KrD1O@+ILPKLoCQO9VZIlK8T z{qz%N5b4^^yTuK;^Z@rqWTd`f`Zb2KiDYSqtSfSpwJ6*)>%@=jFquUqS=6q2OoF${ z&q=Y~H-kZM`vGkW3!~HFr`2d%_ztzm=VZ}@29Ni5i3E%>*~=c7zsjd?7J9EJMBXpZ zqrK-g?0dUCaY7mkq!v3d{JNo;tW9%ixO$^A@%2EK4liOu$ez*FO+Aj6w^zOc*|T#Y z7>6qj`Qa9a2^hl#B_=%o6m}T>s4c>goMV%9Ml5m2fo{;Ht{0=wC8xv;;eUdG^Kg~F zK{mljZ+9IMm8I1`E^SRf{@2bIt~e-tvYLq{LSfr08+$xuzFHDcN!4z1DP{7T@l_%+ zNYN}EqL=r)6L=frp=-5OzE87IQ7#>qpJjU#puyB9`#w?}e!A3P^Ii=Xq_c5azS2lH zzLyoW9u5Oqp1?Z38xpLb^*1X^1l@?Jf~@NG`A`=zA-{}Ke&$0XEScBsUn`>~s76*x zu|k`%h=@qIH9%xCK1D95Z~6eL5Y7sS6S6XLq&jz}a zK#~FUs)A(5qw;#6`X=6j`3-kPmFP~`?0TUn6YS%p=!M%o(_L{wCBE`n4`?Nk(!8ZXrN019TH{mo(4{^j^p zooUe|Rf;)U2djr3?)3!;Q|?^Fc}Z@@o4+PAX@@B!x(FdmPxf5Z|9;3r;=82}9%a0P z!((T89u~o*+uDUAYd}b92l^B-|9F=!Y$GjI449=W+(+8(g%m46W>2HXF>DjGes2Ex zHz+5li0lOl51_ysBHkpa1j7NiX~YP&{Mj|&=1=JwNXVBaKT1u%&Lp9WhIzW!px0a{ z$qVWY7puSjU^da^r7QhN^N{;?ck!(Ab!tx7uZg<70|VbdJ??1x`V>|IVBL+<)2i8RPD zhlUhjqHj7+1C@Qdfc28CAi1-2)_03R!UGUD1Z0gNh3JyHVHQBu4WK5&@o?$oTY(+0 z1g}tmSV#;4{7zUfkV+0f)ldDJ*9Y?!0l9c^xyeykpBVw;PPT`_ry~pi_Gwkr>HsfIICdGzacNs>@+ly|I$eWk|IC~ zfEGvy`8mllhj8%g#V5q@CzAkV!j!F{r3A&$s*@#?j(Gs|59ssj@22u%Rx=oYRwJ;p z!nBE_F}qf?b9|kEC@av#1Zl9vq&}q4@J{NVnaq&x9#x)nNelwSqAj35ELX;v8h|vC zxE}+>2T=b4tvcFkEGinT0rwX-11Q`3nZC5N8JC13p|E4Lxtt5QJ6(RgQa@9CAzFLU>ZTnFh*JaoN5$U9OxGhdf_Gg+yxpE zN(T04@s&Y$XNhdkX0;znM@Ppf&k(-ekp)cwv=>ePpmw~Vql?!V%RTFL@|V+ura1xH zp+Xvyz{?Nr5cLMv-2p28wlM&1%ywUOKmsyN0_sG0RAGvZbSI8{=v5)|tmZ<|04bNQ znO$@r4-l0e*#%^n33JfV9d~60Z8Vo+HQH7Lrzz0%j0dC^I=T!_U!aNqP!JM=Rt0!s zhe&|#4oL8YjxHS#$<~R586d45vonxn32dkBeK46aw-?2AAY6-%j&qA(g)6mD)uO&M zVEQc^M-aNv(UqO|6uA(?^-uP2NwuZGgYf4#7?@NkhFr>f1DXT{9T)*uW(nM$m#egJ zs2VCu4ZlFD{=AQNj?N>i_i{0f^V>5n|xzO&cFN_^(b|!5j(K@%z27v+sBlB<;TT&c-pojer;Uewxm?2OwgExm zHMu58U4|yp16GKb{8RfExeR}??zwxjjQtn`!BSc#V>HIpbd!K)powYy_AX^^%%Qk| zs#2va2BXb?w?OfK7R0`n-L_YPfoq?CFyDQ=2g?Ju#`}D}uQ%KV{VXmq3t6TCZg@Rx zlaX4N*EOZRYsh0X)4OI!ma%jj09$O|w;8_sbL`$5HT$Q(?Iaxux(K=+-Ga?!ZixSI z9w7hg845RQ5j&H^01XIOgqv;7Fu&L2M?a?bhe2wL!`QfhU9(P_x2Cziiex2aAaj8gD3&{Osj(m*|GR_e2 zm$DCXQ=8Tsdtd&0FNf-EMl_1Yfh0|MR_^VZl0oUL-(WA|J{3ebe&4J4w}+JSOdo{u zv5F}iK!+fEYu>#PbhNySy)_^SbVmjjF`-3GA{3vjl3^$$li3_mQfZVo`|{EFjUD&v z{Jcjv3^&alBe5d*Y+9L0S>TLnAp}PDRyiJemEf-+NY@q#*g$tvhZzo}e9D74%{2Q2 zPf4cie_g@UObp+1h52!(;hSWxnkJ?E_ui?BErn%`8i#A}DXKRy9pCyv#c*EGWjxji ztAPH5ly7!Ce!7w%MdiL`sbu(mNmLrA}pMX7Fdur0o#Q&ff27;DX`Xhw{fP!kw@D%~6v-j8JssVf9T}r%C zJEGh~nb|7VpLZ7M15WC&!3X9@110Uzct*Q{N-h_LE-M$8Nz2uBjKxo)~wty%jCMWwzDa1iqlH&Dwx*s z?wO#Hl1FVk)NTNrr*(6o^AEI$0lS@-k=AafVr(q$s$hT@YRiyA$@5{3b~c+@t7iAg zVtsVNkhqhDx{|2VY=9S96(B8JRY1R6P0JubLL|#KaAz;PGV;gmiRb2gCjmd|fz^i> zLHua~DrR2L$O8-=9O>Y6IZZuASNz4*YmHm6>nh{-xz3tKmZS9j!|5U{V0yKV^4aq={ebNO~n9IP3~Tjh`Zq1j~RLr-h&q?7rCiH>g1FHQtV z_HiOEphXMN-GV$p z^*sT|AFVl}e*_CwK#FU~_P$4hM7uc^Db^n|Hw-3`zIeaE`k>w}`fCf0TaaR{n!C~~ z!na!RmnWZiW#u7W3|dz^4!TD*+Q@G!WA}C5XC^jrsHZ+t^RAusxsZ{xz4@ZOdRFY5 zzB6q?wFM$>@(n)Bg6dn%qUK2PF1#SGB&$A#aW_Rd0#QI{0*v+w6J&_uY_O%woW zXlx>ra-g;}al^uIZR2O`Y7D1}=^Oo~`Km$V)Iu2Rp(#H)#YgQWxeAQ2OcBiR^8%qW zE+Bb-9yFhX&TSyIluvCnWUt2u?7Q+(Av-e=GYC8_PelGP=yZtnW>7)sTd&KArB=c5 zJAKos6Gv^Y%&Uszlnt2{kbR7qFA3egz_i$S_wzq3CAh{*pyzt}q2mE&I*lz*pWakR zaV=!9YXemEQExN5?q<$=6=(6Yk3x@UNu*z%85S?@_cU(Gd$X1 zO`@rdh1WR8i{8kay}u^w^v>NJ#SDt57&2<`GOl%OySvbP?~^^*vNk^Tez!TsWK8dg!ry zd!^4%5WdQ!oE{uI5ecdvZ$-2 z&+Z4Nd~^c=GzNBHYN#$o@XK4Y?0uD5%``v&*d6P<-ltwY#Brx|PBm{$hXc2&O4;uG z2AZR#CPWqrs=uKKvVqrviv%Q6T!J@3onQl-gr=8iEFh8tK_TcM8+;77OcH&z`NDyF z==v3Cv-5D-Ld?zRAxg;?>lcBZu z?EV-7StBX63h^|(Xg7=LbHb7KB;8w0Px=(xK6pIF8Q=ttF?_m45V-w2+J~kh2dVq5 zP@1WnbkGL0gz3a)z@$M3+l-(hpluE!1(0`NiC;nX_MJNmJXW;l2x})g>i3KxGL}Vm z0n(dxjK2y6cOZu0p{l__x&Jln5r>J-?eu^|2Da-3%45sJOxZ#}1RZqait0D0&Bi{n z0V050m!W1!rcdM;bO8(oqH4TMZ>2GCL7+Y;Kox$Ka6h0#IGA;3>8ywC(#UTdLLVVi zbxr@@K$&y2hB_-3q$ZA_o@qi4lRS6klqkYEfp{K>FkP54-$5OEg-n1_D2{fhx=_NiWcmq3lQzd9SwRo@P4Zhr}Q?1PSsj~XIB{#Gk4yw@3 zfR-^U`jU`#BlS(8inbMbNpVAPDy`{-tXAd_HK9n2Er}pfy_wOtB9g177Wo=Pw!kBD z@G>9u36w!YOMr@lYylc);PpcHQET4b8370ryuSY9wSS~Og$SM|PYS;N6`Fi5hZ1Tf z8Pqch4t|qPy9M|&X!`?fDmT<(Nk~ZK(=VEhtl&EVW3yy#KkU`9TS2WAsR*Q@SJiS0 zGI25(4I!ZyBLPz}ry+qK;Jt#?wGDK;0XHh!50ojvf48{OT2FxIorI7b@C4MSez%Wy z`$4M4Gx%H$G>(R*25O5G7!ynX10h2{*%pDk5 zxOOffa10F9;#+t9#MY7k!^L~@?-fwNW6iBZ93UzL1MBeYr(Pz|tOKE_;DP&`wBD** z4*I>GTAYC62(6A~-7@gXnsq-vr|Ym_;JKR3TtnBq;w$$bf1yl{osjLD{OjoDc(1Dq zvMzJ*UZ>#x(|TA_@JWVOZ@zx`$Em0hNAvHzXgg|C6zVDgE1u%IOOWVjN?@4Vawlb5 zpXffcW^7R~UQQ5Q#Npj8ofPw(C#&db<%89KGu}*Fdzyf8{J73#Bl%WY1Ir}$Rz2Y_ z2zBcy&Zai3;e7u}f$iDKSMqE(?=ROOIjfZ8I zUd)H00+e%qdfRnB6hs4>_SZOQG^l^~KQwuY`SBBv++Xi|0=3S={QZaTx6jF&9l*C@ zobt~is~}Zympq%n`SZ9tlia)YgufxKT1Tm);xb%>$hUwN=YR6y0Fb)tiZ`_Vk1t?i zjlz|O^oK5RsM?p||SnOl^1ya$BWTPN#|+^P>vNZ{y{TUi`pw*Z3ecwSU`ahdN9<_d_rpDx7>P69<-(KTI|;bkE|l`}^TuXO#fyE!CAd)9wr6-1lF--cQf`zq&;B zGJN_2)4aI&{?&@5j+;LoOxDSOm1Q3PMLtFqzY7VI1RIvt=^}n?Ye%_UC>d!|(s9OZ~($vaHdEC`Ikm$dS|jP|q9jA&7+|FmpDm87R--h~s!k zq{PJ$RRyTVBISmK>a1LAk3xC>SCb}mny%f)@|ePAtK7`!2qIytys|Nwm;+=53~b8} zKdMwbi&7?sm?$=mD8}GtH-U;l1GLYB<3(tqS1?hysde7)+SST>AR~?*npWMrV&H(; z0!jw|%Ggv6i?Yg^!CbL%r|z{2-6+_-{kxx{Jj1mfZFW!d=i7WQU`3gdy9)qg{Ce~P zMPgt7?z+N>JwbI?sgk=>kwcAz-EvNhCG~T2Gj=n|90mG-?h8FBeE`hhRqCn}`R9f9 z5B9HeSWCIKvny`zhep_NXZHfxCz=J$uk2F5a;&OdJf_DV28wd8Si0{#zm411Qw%xx z)a$?>e)79oDhqq-T@55*p-MwpA{0CZ!R^l>K?XSyqMR53t5n$y^g?U}>aDg1HTs;C zB3Gs6vkwee@n1H~(M>g)wq{cIWl)vCB#FAGjJ)X)PWDhdV8)q^n`oG@yf=MszKvtc zpHDf8R*+C&&L9|=NvS4%Fhq<$kHBdc=CpV_UJ1!JpZd+j9 zDc)-Oi(NRWkiQa#>2IP$NsvDjQ~vfm|Hokw6=84(c^B~$&q_j+)ujakS%<4(XMLG@ zstjIlWKm||8rqNuzYf(ey31zQ6cbIRrUeSh-yA|{jp?-B>xVNok3X*@wnsfWN7N61 zDNnn6z;@49e)kyFJDOh*+2==$ExZxc;AveoMPw>IZjqlW)rwB)LD))TL~EV6U{Ms? zgfukHsU!Mjjp=v7qt<;lzmn{tEd%y+E3|z1JYRI9=mH@(+On`9Pjrhg!Z_4u4Ag4l3EK#woiE9@gX|__iM@Cg2cg^ z9X}FGZHzpmG9(W5POR@oXH1+nSl`*OMHl6mYjyd-opNvKM4uUzZJbsXcIobv*d_V7 zy>Y(#%KU?oBdWo|sMO?V8=|UI2U>|<-H0@ELyO!V>rI_cMy~ekmkM3TIpx=1_<=A} z?ABlj3p|4`KXJYw-n00q-wpSI8CijM&wXBnhqeT{Kdj2p6|R1^s|`A znk{n2jAzLb-m^X@N(HwA#tTgt7v}U80@cz3bsUE>bP7}}7PlHwJR}!FhmulqJZ9_X)kuo5HlcIV z-%vpwBS$5RIx^TBl>?T1rH@mfnNvM~7T==B+%I|zt@*0x3tr9v@|f3m%S7^v#JUbL zYR|&nCR_1`Znz}NX=NMv+jGvY6y@nSlXN6j+S_1^H&NUV4tnjpW%QjoasK)X)nF6v zVIIMFQOPjRInqPR@?p}O4g}AMg<@&m)KE*qd#wBR8{xeY_xK)56K91FMps)sEqQYU zH))d0l-YWs{wg|6kq#}ueGjL{Rx{)>BAS1c;p^Pv4cYG2EjUv&&~1@QJ1@;JhKm6P zY+=DaYUFd_!Yk{bkwej>ff15z(#L4GLP|2{tCY5JGT2a};QI_oWJDuDeJd_v zI(kR-NJL9$t*I1BnIVw`vTAw2mw7}{F(s7Yfe+}sW^^26HP-b|-e-~kF#GA+zTXWkkeg|-FF z2j+3t#L{pIh6SQk9&beqGH{^QHta!NSpi4aLXtP?9x-Ct_C33MO8J{gCt`sw2P}DJR-D4%%bR;VhA$v6k;pd*LBU+DWsWg8!k%G{!KQ+tk zL5_w|2-neR`OUu9y?a=h-MrkJ;-42CX{xFmNg8yoSA@UE)w*bLx+_}bH#VV5*x+VO zjZL4~SvS9#{d}`1>=N0t%20G?#x%nt{_0K_FCV?$0(MJpwjZQeFE7$Gg9E~jSTGckPh%54eB8w!a!<8}dKhM`4X)ddfx9LeQmoOOf2WkgRE zed!xqEfBgI_jr}l$Eg-#mC`mU%Y84)aUeMUO-jy#Q_VT0??#k+UA8|R(VHmnF!aWs zHSV$8C}D%iF63|=v^j{)P*urqXcGaR?%#(c8gW3}=N~-F9vnjQY7Wy6iS{D{Z$>|` z%8-4M(i+%f06wP;;lRIr~dmjiP)xO0i%81j_yt@~x&1%`IixXD` z75|?EcOdPu5_y1F`@amNeh#@n^us4XMYjxIEA}8KJ{HQgP=gG$xh()6S+QqSBljPD zNCZlmj@nRAOg%3C{RPC)MZMl6>AG_3avIjM>b8+8Kmg~-e}z|MKuYZY&i!49Pu2|y zIh%e)Wd3>iuh_ny{as)i?f##^G5>o@1f28#Wq|y%!}i}|68}#jmjGH5HSX&{v#kXg zX_`3?q7VbLV|~@q`yWGU!Q!Q1+$oKyMr0KF4 literal 0 HcmV?d00001 From 3c01f9df51ab03cbb10490944573c4a53ff830cf Mon Sep 17 00:00:00 2001 From: ninod Date: Wed, 22 Nov 2017 14:59:51 -0600 Subject: [PATCH 05/19] adding documentation folder --- ...ercodegendiagram1.PNG => swaggercodegnimage.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/swagger-codegen/src/main/resources/pkmst/docs/{pkmstswaggercodegendiagram1.PNG => swaggercodegnimage.png} (100%) diff --git a/modules/swagger-codegen/src/main/resources/pkmst/docs/pkmstswaggercodegendiagram1.PNG b/modules/swagger-codegen/src/main/resources/pkmst/docs/swaggercodegnimage.png similarity index 100% rename from modules/swagger-codegen/src/main/resources/pkmst/docs/pkmstswaggercodegendiagram1.PNG rename to modules/swagger-codegen/src/main/resources/pkmst/docs/swaggercodegnimage.png From 81749f527f974baf7c40ee51d878b1e5f10a3293 Mon Sep 17 00:00:00 2001 From: ninodpillai Date: Wed, 22 Nov 2017 15:25:04 -0600 Subject: [PATCH 06/19] Update readme.mustache Added feature set offered by pkmst --- .../src/main/resources/pkmst/readme.mustache | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache index e803d782c37..1fad493459f 100644 --- a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache +++ b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache @@ -1,4 +1,31 @@ -This is the sample Pkmst microservice template project generated from swagger codegen.Using swagger specification you can convert any definition to spring boot microservice. +Dear Reader : Thanks for Selecting PKMST swagger code generation toolkit for starting your microservice journey. +We believe the hard work we put into this framework will help you kick start your journey sooner and you will find it +easy to scale your service to enterprise grade. Another great thgin is you dont need to enable all capabilities as you start, +but can enable as your microservice capabilities needs to be extended to meet strict enterprise standards. + +PKMST feature set. +a)Read the Swagger supplied and will create a maven project +b)Create basic controller based on rest verb and path configured in swagger +c)generate default unit test cose using junit +d)generate all needed dependency needed to run the microservice on local +e)generate a default manifest file that allows you to push code to cloudfoundry instance ( eg pcf , ibm bluemix etc) + +As you mature your knowledge with pkmst, yoe can levereage vendor extensions feature that will allow you to supply specific configuration +in your swagger and generate respective configuration that will +f)Allow you integrate with registry server (Example Eureka) +g)Allow you to integrate with tracing server (Example Zipkin) +h)Allow you to capture log in your microservice and send to Log management server (Ex ELK or splunk) +i)Allow you to configure Oauth2 security based authorization for your microservice + + Additonal Features + j)generate sample cucumber file and dependency to drive your Behaviour driven development. + k)generate gatling based perfromance test , which can be excuted via build pipeline like jenkins etc. + + + + +Working +Using swagger specification you can convert any definition to spring boot microservice. It has the integration with the below services: eureka registry, zipkin , spring boot admin, circuit breaker. From 2595347b6e3c46eca62f12d62beb50d35887b33f Mon Sep 17 00:00:00 2001 From: sanshuman Date: Thu, 23 Nov 2017 15:32:06 +0530 Subject: [PATCH 07/19] updated readme --- .../src/main/resources/pkmst/readme.mustache | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache index 1fad493459f..da880fb877c 100644 --- a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache +++ b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache @@ -1,6 +1,6 @@ -Dear Reader : Thanks for Selecting PKMST swagger code generation toolkit for starting your microservice journey. +Dear Reader : Thanks for selecting PKMST swagger code generation toolkit for starting your microservice journey. We believe the hard work we put into this framework will help you kick start your journey sooner and you will find it -easy to scale your service to enterprise grade. Another great thgin is you dont need to enable all capabilities as you start, +easy to scale your service to enterprise grade. Another great thing is you don't need to enable all capabilities as you start, but can enable as your microservice capabilities needs to be extended to meet strict enterprise standards. PKMST feature set. @@ -10,7 +10,7 @@ c)generate default unit test cose using junit d)generate all needed dependency needed to run the microservice on local e)generate a default manifest file that allows you to push code to cloudfoundry instance ( eg pcf , ibm bluemix etc) -As you mature your knowledge with pkmst, yoe can levereage vendor extensions feature that will allow you to supply specific configuration +As you mature your knowledge with pkmst, you can leverage vendor extensions feature that will allow you to supply specific configuration in your swagger and generate respective configuration that will f)Allow you integrate with registry server (Example Eureka) g)Allow you to integrate with tracing server (Example Zipkin) @@ -22,8 +22,6 @@ i)Allow you to configure Oauth2 security based authorization for your microservi k)generate gatling based perfromance test , which can be excuted via build pipeline like jenkins etc. - - Working Using swagger specification you can convert any definition to spring boot microservice. It has the integration with the below services: @@ -101,10 +99,6 @@ interceptor: For testing we have placeholders for junit test class, integration test class, cucumber sample feature file(implement according to your needs), gatling load test. - - - - Ways to run the project: 1) Normal spring boot application From 73a0c992bc223c592999259c04b80e83d456b658 Mon Sep 17 00:00:00 2001 From: ninodpillai Date: Sat, 25 Nov 2017 21:53:24 -0600 Subject: [PATCH 08/19] Update io.swagger.codegen.CodegenConfig Arranged pkmstServerCodeGen and SymfonyServerCodegen in aphabatical order --- .../META-INF/services/io.swagger.codegen.CodegenConfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 51df86c0b9a..6e77a191262 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -47,7 +47,7 @@ io.swagger.codegen.languages.NodeJSServerCodegen io.swagger.codegen.languages.ObjcClientCodegen io.swagger.codegen.languages.PerlClientCodegen io.swagger.codegen.languages.PhpClientCodegen -io.swagger.codegen.languages.SymfonyServerCodegen +io.swagger.codegen.languages.PkmstServerCodegen io.swagger.codegen.languages.PowerShellClientCodegen io.swagger.codegen.languages.PistacheServerCodegen io.swagger.codegen.languages.PythonClientCodegen @@ -74,6 +74,7 @@ io.swagger.codegen.languages.SwaggerYamlGenerator io.swagger.codegen.languages.Swift4Codegen io.swagger.codegen.languages.Swift3Codegen io.swagger.codegen.languages.SwiftCodegen +io.swagger.codegen.languages.SymfonyServerCodegen io.swagger.codegen.languages.TizenClientCodegen io.swagger.codegen.languages.TypeScriptAureliaClientCodegen io.swagger.codegen.languages.TypeScriptAngularClientCodegen @@ -83,4 +84,3 @@ io.swagger.codegen.languages.TypeScriptJqueryClientCodegen io.swagger.codegen.languages.TypeScriptNodeClientCodegen io.swagger.codegen.languages.UndertowCodegen io.swagger.codegen.languages.ZendExpressivePathHandlerServerCodegen -io.swagger.codegen.languages.PkmstServerCodegen \ No newline at end of file From f4a4c6f56f9aa6c02623fdd7c0890966a1a71813 Mon Sep 17 00:00:00 2001 From: rkumar-pk Date: Thu, 30 Nov 2017 15:16:11 +0530 Subject: [PATCH 09/19] Update readme.mustache --- .../swagger-codegen/src/main/resources/pkmst/readme.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache index da880fb877c..27d8199c6f7 100644 --- a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache +++ b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache @@ -22,7 +22,7 @@ i)Allow you to configure Oauth2 security based authorization for your microservi k)generate gatling based perfromance test , which can be excuted via build pipeline like jenkins etc. -Working +Working: Using swagger specification you can convert any definition to spring boot microservice. It has the integration with the below services: eureka registry, zipkin , spring boot admin, circuit breaker. From ad08778618a05f14bc478e4aea465f49098b7f07 Mon Sep 17 00:00:00 2001 From: sanshuman Date: Tue, 5 Dec 2017 23:20:57 +0530 Subject: [PATCH 10/19] renamed according to convention and added typeinfoannotation --- .../languages/JavaPKMSTServerCodegen.java | 1472 +++++++++++++++++ .../codegen/languages/PkmstServerCodegen.java | 1457 ---------------- .../services/io.swagger.codegen.CodegenConfig | 2 +- .../pkmst/typeInfoAnnotation.mustache | 7 + 4 files changed, 1480 insertions(+), 1458 deletions(-) create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java delete mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/typeInfoAnnotation.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java new file mode 100644 index 00000000000..0e9295d2126 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java @@ -0,0 +1,1472 @@ +package io.swagger.codegen.languages; + +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.ListIterator; +import java.util.Map; + +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; + +import io.swagger.codegen.CliOption; +import io.swagger.codegen.CodegenConfig; +import io.swagger.codegen.CodegenConstants; +import io.swagger.codegen.CodegenModel; +import io.swagger.codegen.CodegenOperation; +import io.swagger.codegen.CodegenParameter; +import io.swagger.codegen.CodegenProperty; +import io.swagger.codegen.CodegenResponse; +import io.swagger.codegen.CodegenType; +import io.swagger.codegen.DefaultCodegen; +import io.swagger.codegen.SupportingFile; +import io.swagger.models.Model; +import io.swagger.models.Operation; +import io.swagger.models.Path; +import io.swagger.models.Swagger; +import io.swagger.models.Tag; +import io.swagger.models.parameters.FormParameter; +import io.swagger.models.parameters.Parameter; +import io.swagger.models.properties.ArrayProperty; +import io.swagger.models.properties.BooleanProperty; +import io.swagger.models.properties.DoubleProperty; +import io.swagger.models.properties.FloatProperty; +import io.swagger.models.properties.IntegerProperty; +import io.swagger.models.properties.LongProperty; +import io.swagger.models.properties.MapProperty; +import io.swagger.models.properties.Property; +import io.swagger.models.properties.StringProperty; + +/** + * Created by prokarma on 04/09/17. + */ +public class JavaPKMSTServerCodegen extends DefaultCodegen implements CodegenConfig { + + public static final String FULL_JAVA_UTIL = "fullJavaUtil"; + public static final String SUPPORT_JAVA6 = "supportJava6"; + public static final String CONFIG_PACKAGE = "configPackage"; + public static final String BASE_PACKAGE = "basePackage"; + public static final String TITLE = "title"; + public static final String WITH_XML = "withXml"; + public static final String EUREKA_URI = "eurekaUri"; + public static final String ZIPKIN_URI = "zipkinUri"; + public static final String SPRINGADMIN_URI = "springBootAdminUri"; + protected String groupId = "com.prokarma"; + protected String artifactId = "pkmst-microservice"; + protected String artifactVersion = "1.0.0"; + protected String projectFolder; + + protected String projectTestFolder; + protected String sourceFolder; + protected String testFolder; + protected String basePackage = "com.prokarma.pkmst"; + protected String serviceName = "Pkmst"; + protected String configPackage = "com.prokarma.pkmst.config"; + protected boolean implicitHeaders = false; + protected boolean serializeBigDecimalAsString = false; + protected boolean withXml = false; + protected boolean fullJavaUtil; + protected String javaUtilPrefix = ""; + protected Boolean serializableModel = false; + protected String invokerPackage; + protected String title; + protected String apiDocPath = "docs/"; + protected String modelDocPath = "docs/"; + protected String eurekaUri; + protected String zipkinUri; + protected String springBootAdminUri; + + public JavaPKMSTServerCodegen() { + super(); + this.projectFolder = "src" + File.separator + "main"; + this.projectTestFolder = "src" + File.separator + "test"; + this.sourceFolder = this.projectFolder + File.separator + "java"; + this.testFolder = this.projectTestFolder + File.separator + "java"; + embeddedTemplateDir = templateDir = "pkmst"; + apiPackage = "com.prokarma.pkmst.controller"; + modelPackage = "com.prokarma.pkmst.model"; + invokerPackage = "com.prokarma.pkmst.controller"; + setReservedWordsLowerCase(Arrays.asList( + // used as internal variables, can collide with parameter names + "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", "localVarHeaderParams", + "localVarFormParams", "localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes", + "localVarContentType", "localVarAuthNames", "localReturnType", "ApiClient", "ApiException", + "ApiResponse", "Configuration", "StringUtil", + + // language reserved words + "abstract", "continue", "for", "new", "switch", "assert", "default", "if", "package", "synchronized", + "boolean", "do", "goto", "private", "this", "break", "double", "implements", "protected", "throw", + "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", + "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while", "null")); + + this.languageSpecificPrimitives = new HashSet(Arrays.asList("String", "boolean", "Boolean", "Double", + "Integer", "Long", "Float", "Object", "byte[]")); + this.instantiationTypes.put("array", "ArrayList"); + this.instantiationTypes.put("map", "HashMap"); + this.typeMapping.put("date", "Date"); + this.typeMapping.put("file", "File"); + + this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); + this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); + this.cliOptions.add(new CliOption("serviceName", "Service Name")); + this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); + this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); + this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); + this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); + // Middleware config + this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); + this.apiTestTemplateFiles.put("api_test.mustache", ".java"); + this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); + this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); + } + + private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { + // This generator uses inline classes to define enums, which breaks when + // dealing with models that have subTypes. To clean this up, we will + // analyze + // the parent and child models, look for enums that match, and remove + // them from the child models and leave them in the parent. + // Because the child models extend the parents, the enums will be + // available via + // the parent. + + // Only bother with reconciliation if the parent model has enums. + if (!parentCodegenModel.hasEnums) { + return codegenModel; + } + + // Get the properties for the parent and child models + final List parentModelCodegenProperties = parentCodegenModel.vars; + List codegenProperties = codegenModel.vars; + + // Iterate over all of the parent model properties + boolean removedChildEnum = false; + for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { + // Look for enums + if (parentModelCodegenPropery.isEnum) { + // Now that we have found an enum in the parent class, + // and search the child class for the same enum. + Iterator iterator = codegenProperties.iterator(); + while (iterator.hasNext()) { + CodegenProperty codegenProperty = iterator.next(); + if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { + // We found an enum in the child class that is + // a duplicate of the one in the parent, so remove it. + iterator.remove(); + removedChildEnum = true; + } + } + } + } + + if (removedChildEnum) { + // If we removed an entry from this model's vars, we need to ensure + // hasMore is + // updated + int count = 0, numVars = codegenProperties.size(); + for (CodegenProperty codegenProperty : codegenProperties) { + count += 1; + codegenProperty.hasMore = (count < numVars) ? true : false; + } + codegenModel.vars = codegenProperties; + } + return codegenModel; + } + + private static String getAccept(Operation operation) { + String accepts = null; + String defaultContentType = "application/json"; + if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String produces : operation.getProduces()) { + if (defaultContentType.equalsIgnoreCase(produces)) { + accepts = defaultContentType; + break; + } else { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(produces); + } + } + if (accepts == null) { + accepts = sb.toString(); + } + } else { + accepts = defaultContentType; + } + + return accepts; + } + + public CodegenType getTag() { + return CodegenType.SERVER; + } + + public String getName() { + return "pkmst"; + } + + public String getHelp() { + return "Generates a Java SpringBoot Server application using the SpringFox integration." + + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; + } + + public void processOpts() { + super.processOpts(); + if (this.additionalProperties.containsKey("basePackage")) { + this.setBasePackage((String) this.additionalProperties.get("basePackage")); + this.setInvokerPackage(this.getBasePackage()); + this.apiPackage = this.getBasePackage() + ".controller"; + this.modelPackage = this.getBasePackage() + ".model"; + this.setConfigPackage(this.getBasePackage() + ".config"); + + // this.additionalProperties.put(BASE_PACKAGE, + // this.getBasePackage()); + } else { + this.additionalProperties.put(BASE_PACKAGE, basePackage); + this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); + this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); + this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); + this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + } + if (this.additionalProperties.containsKey("groupId")) { + this.setGroupId((String) this.additionalProperties.get("groupId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.GROUP_ID, groupId); + } + if (this.additionalProperties.containsKey("artifactId")) { + this.setArtifactId((String) this.additionalProperties.get("artifactId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); + } + if (this.additionalProperties.containsKey("artifactVersion")) { + this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + } + if (this.additionalProperties.containsKey("serviceName")) { + this.setServiceName((String) this.additionalProperties.get("serviceName")); + } else { + // not set, use to be passed to template + additionalProperties.put("serviceName", serviceName); + } + + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { + this.setSerializeBigDecimalAsString(Boolean.valueOf( + this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); + } + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { + this.setSerializableModel( + Boolean.valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); + } + if (this.additionalProperties.containsKey(TITLE)) { + this.setTitle((String) this.additionalProperties.get(TITLE)); + } + this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); + if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { + this.setFullJavaUtil(Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); + } + + if (this.additionalProperties.containsKey(EUREKA_URI)) { + this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); + } + if (this.additionalProperties.containsKey(ZIPKIN_URI)) { + this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); + } + if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { + this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); + } + if (fullJavaUtil) { + javaUtilPrefix = "java.util."; + } + this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); + this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); + this.additionalProperties.put(SUPPORT_JAVA6, false); + this.additionalProperties.put("java8", true); + + if (this.additionalProperties.containsKey(WITH_XML)) { + this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); + } + this.additionalProperties.put(WITH_XML, withXml); + + // make api and model doc path available in mustache template + this.additionalProperties.put("apiDocPath", apiDocPath); + this.additionalProperties.put("modelDocPath", modelDocPath); + + this.importMapping.put("List", "java.util.List"); + + if (fullJavaUtil) { + this.typeMapping.put("array", "java.util.List"); + this.typeMapping.put("map", "java.util.Map"); + this.typeMapping.put("DateTime", "java.util.Date"); + this.typeMapping.put("UUID", "java.util.UUID"); + this.typeMapping.remove("List"); + this.importMapping.remove("Date"); + this.importMapping.remove("Map"); + this.importMapping.remove("HashMap"); + this.importMapping.remove("Array"); + this.importMapping.remove("ArrayList"); + this.importMapping.remove("List"); + this.importMapping.remove("Set"); + this.importMapping.remove("DateTime"); + this.importMapping.remove("UUID"); + this.instantiationTypes.put("array", "java.util.ArrayList"); + this.instantiationTypes.put("map", "java.util.HashMap"); + } + // optional jackson mappings for BigDecimal support + this.importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); + this.importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); + + // imports for pojos + this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); + this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); + this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); + this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); + this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); + this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); + this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); + this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); + this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); + this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); + this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); + this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); + this.importMapping.put("IOException", "java.io.IOException"); + this.importMapping.put("Objects", "java.util.Objects"); + this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); + // import JsonCreator if JsonProperty is imported + // used later in recursive import in postProcessingModels + this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", + "com.fasterxml.jackson.annotation.JsonCreator"); + + this.apiTemplateFiles.put("api.mustache", ".java"); + this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); + + this.modelTemplateFiles.put("model.mustache", ".java"); + + this.supportingFiles.add(new SupportingFile("SpringBootApplication.mustache", + (this.getSourceFolder() + File.separator + this.getBasePackage()).replace(".", File.separator), + this.getServiceName() + "Application" + ".java")); + + this.supportingFiles + .add(new SupportingFile("config" + File.separator + "swaggerDocumentationConfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", + java.io.File.separator) + File.separator + "swagger", + "SwaggerDocumentationConfig.java")); + + this.supportingFiles.add(new SupportingFile("config" + File.separator + "pkmstproperties.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator + "swagger", + "PkmstProperties.java")); + this.supportingFiles.add(new SupportingFile("config" + File.separator + "appconfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator, + "AppConfig.java")); + + // Security + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "authorizationServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "AuthorizationServerConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "oAuth2SecurityConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "OAuth2SecurityConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "resourceServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "ResourceServerConfiguration.java")); + + // logging + + this.supportingFiles.add(new SupportingFile("logging" + File.separator + "httpLoggingFilter.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + File.separator + + "logging", + "HttpLoggingFilter.java")); + + // Resources + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-local.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-local.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev-config.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev-config.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "bootstrap.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + + // POM + this.supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + + // Readme + this.supportingFiles.add(new SupportingFile("readme.mustache", "", "Readme.md")); + + // manifest + + this.supportingFiles.add(new SupportingFile("manifest.mustache", "", "manifest.yml")); + + // docker + this.supportingFiles.add(new SupportingFile("docker.mustache", "", "Dockerfile")); + + // logstash + + this.supportingFiles.add(new SupportingFile("logstash.mustache", "", "logstash.conf")); + + // Cucumber + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "executeReport.mustache", + this.testFolder + File.separator + this.basePackage.replace(".", File.separator) + File.separator + + "cucumber" + File.separator + "report", + "ExecuteReport.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberTest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Test.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberSteps.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Steps.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "package.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "package-info.java")); + + // test resources + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "cucumber.mustache", + (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "cucumber", + serviceName + ".feature")); + + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "bootstrap.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.properties")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application-test.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application-test.properties")); + + // Gatling + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "gatling.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "gatling.conf")); + + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.conf")); + + this.supportingFiles.add(new SupportingFile( + "gatling" + File.separator + "testapi.mustache", ("src") + File.separator + ("test") + File.separator + + ("scala") + File.separator + ("scalaFiles").replace(".", java.io.File.separator), + "testapi.scala")); + + /* + * this.supportingFiles.add(new SupportingFile( "gatling" + + * File.separator + "package.mustache", ("src")+ File.separator + + * ("test")+ File.separator + ("scala")+ File.separator + + * ("scalaFiles").replace(".", java.io.File.separator), + * "package.info")); + */ + + // adding class for integration test + this.supportingFiles.add(new SupportingFile( + "integration" + File.separator + "integrationtest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "controller", + serviceName + "IT.java")); + } + + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (final CodegenOperation operation : ops) { + List responses = operation.responses; + if (responses != null) { + for (final CodegenResponse resp : responses) { + if ("0".equals(resp.code)) { + resp.code = "200"; + } + doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + resp.dataType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + resp.containerType = returnContainer; + } + }); + } + } + + doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + operation.returnType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + operation.returnContainer = returnContainer; + } + }); + + if (implicitHeaders) { + removeHeadersFromAllParams(operation.allParams); + } + } + } + + return objs; + } + + /** + * This method removes header parameters from the list of parameters and + * also corrects last allParams hasMore state. + * + * @param allParams + * list of all parameters + */ + private void removeHeadersFromAllParams(List allParams) { + if (allParams.isEmpty()) { + return; + } + final ArrayList copy = new ArrayList(allParams); + allParams.clear(); + + for (CodegenParameter p : copy) { + if (!p.isHeaderParam) { + allParams.add(p); + } + } + allParams.get(allParams.size() - 1).hasMore = false; + } + + /** + * @param returnType + * The return type that needs to be converted + * @param dataTypeAssigner + * An object that will assign the data to the respective fields + * in the model. + */ + private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { + final String rt = returnType; + if (rt == null) { + dataTypeAssigner.setReturnType("Void"); + } else if (rt.startsWith("List")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("List"); + } + } else if (rt.startsWith("Map")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); + dataTypeAssigner.setReturnContainer("Map"); + } + } else if (rt.startsWith("Set")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("Set"); + } + } + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + + swaggerType = getAlias(swaggerType); + + // don't apply renaming on types from the typeMapping + if (this.typeMapping.containsKey(swaggerType)) { + return this.typeMapping.get(swaggerType); + } + + if (null == swaggerType) { + LOGGER.error("No Type defined for Property " + p); + } + return toModelName(swaggerType); + } + + @Override + public String getAlias(String name) { + if (typeAliases.containsKey(name)) { + return typeAliases.get(name); + } + return name; + } + + @Override + public String toModelName(final String name) { + // We need to check if import-mapping has a different model for this + // class, so + // we use it + // instead of the auto-generated one. + if (this.importMapping.containsKey(name)) { + return this.importMapping.get(name); + } + + final String sanitizedName = sanitizeName(name); + + String nameWithPrefixSuffix = sanitizedName; + if (!StringUtils.isEmpty(modelNamePrefix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; + } + + if (!StringUtils.isEmpty(modelNameSuffix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; + } + + // camelize the model name + // phone_number => PhoneNumber + final String camelizedName = camelize(nameWithPrefixSuffix); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(camelizedName)) { + final String modelName = "Model" + camelizedName; + LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); + return modelName; + } + + // model name starts with number + if (camelizedName.matches("^\\d.*")) { + final String modelName = "Model" + camelizedName; // e.g. + // 200Response + // => + // Model200Response + // (after + // camelize) + LOGGER.warn( + name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName); + return modelName; + } + + return camelizedName; + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + if (serializeBigDecimalAsString) { + if (property.baseType.equals("BigDecimal")) { + // we serialize BigDecimal as `string` to avoid precision loss + property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); + + // this requires some more imports to be added for this model... + model.imports.add("ToStringSerializer"); + model.imports.add("JsonSerialize"); + } + } + + if (!fullJavaUtil) { + if ("array".equals(property.containerType)) { + model.imports.add("ArrayList"); + } else if ("map".equals(property.containerType)) { + model.imports.add("HashMap"); + } + } + + if (!BooleanUtils.toBoolean(model.isEnum)) { + // needed by all pojos, but not enums + model.imports.add("ApiModelProperty"); + model.imports.add("ApiModel"); + } + + // super.postProcessModelProperty(model, property); + + if ("null".equals(property.example)) { + property.example = null; + } + + // Add imports for Jackson + if (!Boolean.TRUE.equals(model.isEnum)) { + model.imports.add("JsonProperty"); + + if (Boolean.TRUE.equals(model.hasEnums)) { + model.imports.add("JsonValue"); + } + } else { // enum class + // Needed imports for Jackson's JsonCreator + if (this.additionalProperties.containsKey("jackson")) { + model.imports.add("JsonCreator"); + } + } + } + + @Override + public Map postProcessModelsEnum(Map objs) { + objs = super.postProcessModelsEnum(objs); + + // Add imports for Jackson + List> imports = (List>) objs.get("imports"); + List models = (List) objs.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + // for enum model + if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { + cm.imports.add(this.importMapping.get("JsonValue")); + Map item = new HashMap(); + item.put("import", this.importMapping.get("JsonValue")); + imports.add(item); + } + } + + return objs; + } + + @Override + public CodegenModel fromModel(String name, Model model, Map allDefinitions) { + CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); + if (codegenModel.description != null) { + codegenModel.imports.add("ApiModel"); + } + if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { + codegenModel.imports.add("JsonSubTypes"); + codegenModel.imports.add("JsonTypeInfo"); + } + if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { + final Model parentModel = allDefinitions.get(codegenModel.parentSchema); + final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); + codegenModel = JavaPKMSTServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); + } + return codegenModel; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + return objs; + } + + @Override + public Map postProcessModels(Map objs) { + // recursively add import for mapping one type to multiple imports + List> recursiveImports = (List>) objs.get("imports"); + if (recursiveImports == null) { + return objs; + } + + ListIterator> listIterator = recursiveImports.listIterator(); + while (listIterator.hasNext()) { + String _import = listIterator.next().get("import"); + // if the import package happens to be found in the importMapping + // (key) + // add the corresponding import package to the list + if (importMapping.containsKey(_import)) { + Map newImportMap = new HashMap(); + newImportMap.put("import", importMapping.get(_import)); + listIterator.add(newImportMap); + } + } + + return postProcessModelsEnum(objs); + } + + @Override + public void preprocessSwagger(Swagger swagger) { + super.preprocessSwagger(swagger); + if (swagger == null || swagger.getPaths() == null) { + return; + } + if (swagger.getTags() != null) { + System.out.println("Tags are::" + swagger.getTags()); + List resourcePaths = new ArrayList(); + for (Tag tag : swagger.getTags()) { + ResourcePath resourcePath = new ResourcePath(); + resourcePath.setPath(tag.getName()); + resourcePaths.add(resourcePath); + } + this.additionalProperties.put("resourcePaths", resourcePaths); + } + // get vendor extensions + + Map vendorExt = swagger.getInfo().getVendorExtensions(); + if (vendorExt != null && !vendorExt.toString().equals("")) { + if (vendorExt.containsKey("x-codegen")) { + + Map uris = (Map) vendorExt.get("x-codegen"); + if (uris.containsKey("eurekaUri")) { + String eurekaUri = uris.get("eurekaUri"); + additionalProperties.put(EUREKA_URI, eurekaUri); + } + if (uris.containsKey("zipkinUri")) { + String zipkinUri = uris.get("zipkinUri"); + additionalProperties.put(ZIPKIN_URI, zipkinUri); + } + if (uris.containsKey("springBootAdminUri")) { + String springBootAdminUri = uris.get("springBootAdminUri"); + additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); + } + if (uris.containsKey("pkmstInterceptor")) { + String pkmstInterceptor = uris.get("pkmstInterceptor"); + additionalProperties.put("pkmstInterceptor", pkmstInterceptor); + } + } + } + + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() == null) { + continue; + } + for (Operation operation : path.getOperations()) { + boolean hasFormParameters = false; + for (Parameter parameter : operation.getParameters()) { + if (parameter instanceof FormParameter) { + hasFormParameters = true; + } + } + // only add content-Type if its no a GET-Method + if (path.getGet() != null || !operation.equals(path.getGet())) { + String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" + : "application/json"; + String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() + ? defaultContentType : operation.getConsumes().get(0); + operation.setVendorExtension("x-contentType", contentType); + } + String accepts = getAccept(operation); + operation.setVendorExtension("x-accepts", accepts); + } + } + + if ("/".equals(swagger.getBasePath())) { + swagger.setBasePath(""); + } + + if (!additionalProperties.containsKey(TITLE)) { + // From the title, compute a reasonable name for the package and the + // API + String title = swagger.getInfo().getTitle(); + + // Drop any API suffix + if (title != null) { + title = title.trim().replace(" ", "-"); + if (title.toUpperCase().endsWith("API")) { + title = title.substring(0, title.length() - 3); + } + + this.title = camelize(sanitizeName(title), true); + } + additionalProperties.put(TITLE, this.title); + } + + String host = swagger.getHost(); + String port = "8008"; + if (host != null) { + String[] parts = host.split(":"); + if (parts.length > 1) { + port = parts[1]; + } + } + + this.additionalProperties.put("serverPort", port); + if (swagger.getPaths() != null) { + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() != null) { + for (Operation operation : path.getOperations()) { + if (operation.getTags() != null) { + List> tags = new ArrayList>(); + for (String tag : operation.getTags()) { + Map value = new HashMap(); + value.put("tag", tag); + value.put("hasMore", "true"); + tags.add(value); + } + if (tags.size() > 0) { + tags.get(tags.size() - 1).remove("hasMore"); + } + if (operation.getTags().size() > 0) { + String tag = operation.getTags().get(0); + operation.setTags(Arrays.asList(tag)); + } + operation.setVendorExtension("x-tags", tags); + } + } + } + } + } + } + + @Override + public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, + Map> operations) { + String basePath = resourcePath; + if (basePath.startsWith("/")) { + basePath = basePath.substring(1); + } + int pos = basePath.indexOf("/"); + if (pos > 0) { + basePath = basePath.substring(0, pos); + } + + if (basePath.equals("")) { + basePath = "default"; + } else { + co.subresourceOperation = !co.path.isEmpty(); + } + List opList = operations.get(basePath); + if (opList == null) { + opList = new ArrayList(); + operations.put(basePath, opList); + } + opList.add(co); + co.baseName = basePath; + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultApi"; + } + name = sanitizeName(name); + return camelize(name) + "Api"; + } + + @Override + public void setParameterExampleValue(CodegenParameter p) { + String type = p.baseType; + if (type == null) { + type = p.dataType; + } + + if ("File".equals(type)) { + String example; + + if (p.defaultValue == null) { + example = p.example; + } else { + example = p.defaultValue; + } + + if (example == null) { + example = "/path/to/file"; + } + example = "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText(example) + + "\"))"; + p.example = example; + } else { + super.setParameterExampleValue(p); + } + } + + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; + } + + @Override + public String apiFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String apiTestFileFolder() { + return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String modelFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); + } + + @Override + public String apiDocFileFolder() { + return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); + } + + @Override + public String modelDocFileFolder() { + return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName(name); // FIXME: a parameter should not be assigned. + // Also declare the methods + // parameters as 'final'. + + if (name.toLowerCase().matches("^_*class$")) { + return "propertyClass"; + } + + if ("_".equals(name)) { + name = "_u"; + } + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + if (startsWithTwoUppercaseLetters(name)) { + name = name.substring(0, 2).toLowerCase() + name.substring(2); + } + + // camelize (lower first character) the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved word or word starting with number, append _ + if (isReservedWord(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public String toParamName(String name) { + // to avoid conflicts with 'callback' parameter for async call + if ("callback".equals(name)) { + return "paramCallback"; + } + + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + if (inner == null) { + LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning + // null + return null; + } + return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + if (inner == null) { + LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning + // null + return null; + } + return getSwaggerType(p) + ""; + } + return super.getTypeDeclaration(p); + } + + @Override + public String toDefaultValue(Property p) { + if (p instanceof ArrayProperty) { + final ArrayProperty ap = (ArrayProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.ArrayList<%s>()"; + } else { + pattern = "new ArrayList<%s>()"; + } + if (ap.getItems() == null) { + return null; + } + + return String.format(pattern, getTypeDeclaration(ap.getItems())); + } else if (p instanceof MapProperty) { + final MapProperty ap = (MapProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.HashMap<%s>()"; + } else { + pattern = "new HashMap<%s>()"; + } + if (ap.getAdditionalProperties() == null) { + return null; + } + + return String.format(pattern, + String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); + } else if (p instanceof IntegerProperty) { + IntegerProperty dp = (IntegerProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + return "null"; + } else if (p instanceof LongProperty) { + LongProperty dp = (LongProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "l"; + } + return "null"; + } else if (p instanceof DoubleProperty) { + DoubleProperty dp = (DoubleProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "d"; + } + return "null"; + } else if (p instanceof FloatProperty) { + FloatProperty dp = (FloatProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "f"; + } + return "null"; + } else if (p instanceof BooleanProperty) { + BooleanProperty bp = (BooleanProperty) p; + if (bp.getDefault() != null) { + return bp.getDefault().toString(); + } + return "null"; + } else if (p instanceof StringProperty) { + StringProperty sp = (StringProperty) p; + if (sp.getDefault() != null) { + String _default = sp.getDefault(); + if (sp.getEnum() == null) { + return "\"" + escapeText(_default) + "\""; + } else { + // convert to enum var name later in postProcessModels + return _default; + } + } + return "null"; + } + return super.toDefaultValue(p); + } + + @Override + public String toExampleValue(Property p) { + if (p.getExample() != null) { + return escapeText(p.getExample().toString()); + } else { + return super.toExampleValue(p); + } + } + + @Override + public String toOperationId(String operationId) { + // throw exception if method name is empty + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method/operation name (operationId) not allowed"); + } + + operationId = camelize(sanitizeName(operationId), true); + + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + String newOperationId = camelize("call_" + operationId, true); + LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); + return newOperationId; + } + + return operationId; + } + + @Override + protected boolean needToImport(String type) { + return super.needToImport(type) && type.indexOf(".") < 0; + } + + @Override + public String toEnumName(CodegenProperty property) { + return sanitizeName(camelize(property.name)) + "Enum"; + } + + @Override + public String toEnumVarName(String value, String datatype) { + if (value.length() == 0) { + return "EMPTY"; + } + + // for symbol, e.g. $, # + if (getSymbolName(value) != null) { + return getSymbolName(value).toUpperCase(); + } + + // number + if ("Integer".equals(datatype) || "Long".equals(datatype) || "Float".equals(datatype) + || "Double".equals(datatype)) { + String varName = "NUMBER_" + value; + varName = varName.replace("-", "MINUS_"); + varName = varName.replace("\\+", "PLUS_"); + varName = varName.replace("\\.", "_DOT_"); + return varName; + } + + // string + String var = value.replace("\\W+", "_").toUpperCase(); + if (var.matches("\\d.*")) { + return "_" + var; + } else { + return var; + } + } + + @Override + public String toEnumValue(String value, String datatype) { + if ("Integer".equals(datatype) || "Long".equals(datatype) || "Double".equals(datatype)) { + return value; + } else if ("Float".equals(datatype)) { + // add f to number, e.g. 3.14 => 3.14f + return value + "f"; + } else { + return "\"" + escapeText(value) + "\""; + } + } + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, + Map definitions, Swagger swagger) { + CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); + op.path = sanitizePath(op.path); + return op; + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + public boolean convertPropertyToBoolean(String propertyKey) { + boolean booleanValue = false; + if (additionalProperties.containsKey(propertyKey)) { + booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); + } + + return booleanValue; + } + + public String toRegularExpression(String pattern) { + return escapeText(pattern); + } + + @Override + public String sanitizeTag(String tag) { + return camelize(sanitizeName(tag)); + } + + public String toBooleanGetter(String name) { + return "is" + getterAndSetterCapitalize(name); + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getArtifactVersion() { + return artifactVersion; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public String getProjectFolder() { + return projectFolder; + } + + public void setProjectFolder(String projectFolder) { + this.projectFolder = projectFolder; + } + + public String getEurekaUri() { + return eurekaUri; + } + + public void setEurekaUri(String eurekaUri) { + this.eurekaUri = eurekaUri; + } + + public String getZipkinUri() { + return zipkinUri; + } + + public void setZipkinUri(String zipkinUri) { + this.zipkinUri = zipkinUri; + } + + public String getSpringBootAdminUri() { + return springBootAdminUri; + } + + public void setSpringBootAdminUri(String springBootAdminUri) { + this.springBootAdminUri = springBootAdminUri; + } + + public String getProjectTestFolder() { + return projectTestFolder; + } + + public void setProjectTestFolder(String projectTestFolder) { + this.projectTestFolder = projectTestFolder; + } + + public String getSourceFolder() { + return sourceFolder; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } + + public String getTestFolder() { + return testFolder; + } + + public void setTestFolder(String testFolder) { + this.testFolder = testFolder; + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getConfigPackage() { + return configPackage; + } + + public void setConfigPackage(String configPackage) { + this.configPackage = configPackage; + } + + public boolean isImplicitHeaders() { + return implicitHeaders; + } + + public void setImplicitHeaders(boolean implicitHeaders) { + this.implicitHeaders = implicitHeaders; + } + + public boolean isSerializeBigDecimalAsString() { + return serializeBigDecimalAsString; + } + + public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { + this.serializeBigDecimalAsString = serializeBigDecimalAsString; + } + + public boolean isFullJavaUtil() { + return fullJavaUtil; + } + + public void setFullJavaUtil(boolean fullJavaUtil) { + this.fullJavaUtil = fullJavaUtil; + } + + public Boolean getSerializableModel() { + return serializableModel; + } + + public void setSerializableModel(Boolean serializableModel) { + this.serializableModel = serializableModel; + } + + public String getInvokerPackage() { + return invokerPackage; + } + + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public boolean isWithXml() { + return withXml; + } + + public void setWithXml(boolean withXml) { + this.withXml = withXml; + } + + private boolean startsWithTwoUppercaseLetters(String name) { + boolean startsWithTwoUppercaseLetters = false; + if (name.length() > 1) { + startsWithTwoUppercaseLetters = name.substring(0, 2).equals(name.substring(0, 2).toUpperCase()); + } + return startsWithTwoUppercaseLetters; + } + + private String sanitizePath(String p) { + // prefer replace a ", instead of a fuLL URL encode for readability + return p.replace("\"", "%22"); + } + + private interface DataTypeAssigner { + + void setReturnType(String returnType); + + void setReturnContainer(String returnContainer); + } + + private class ResourcePath { + + private String path; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + @Override + public String toString() { + return this.path; + } + } +} diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java deleted file mode 100644 index 286989028ef..00000000000 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PkmstServerCodegen.java +++ /dev/null @@ -1,1457 +0,0 @@ -package io.swagger.codegen.languages; - -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.ListIterator; -import java.util.Map; - -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; - -import io.swagger.codegen.CliOption; -import io.swagger.codegen.CodegenConfig; -import io.swagger.codegen.CodegenConstants; -import io.swagger.codegen.CodegenModel; -import io.swagger.codegen.CodegenOperation; -import io.swagger.codegen.CodegenParameter; -import io.swagger.codegen.CodegenProperty; -import io.swagger.codegen.CodegenResponse; -import io.swagger.codegen.CodegenType; -import io.swagger.codegen.DefaultCodegen; -import io.swagger.codegen.SupportingFile; -import io.swagger.models.Model; -import io.swagger.models.Operation; -import io.swagger.models.Path; -import io.swagger.models.Swagger; -import io.swagger.models.Tag; -import io.swagger.models.parameters.FormParameter; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.ArrayProperty; -import io.swagger.models.properties.BooleanProperty; -import io.swagger.models.properties.DoubleProperty; -import io.swagger.models.properties.FloatProperty; -import io.swagger.models.properties.IntegerProperty; -import io.swagger.models.properties.LongProperty; -import io.swagger.models.properties.MapProperty; -import io.swagger.models.properties.Property; -import io.swagger.models.properties.StringProperty; - -/** - * Created by prokarma on 04/09/17. - */ -public class PkmstServerCodegen extends DefaultCodegen implements CodegenConfig { - - public static final String FULL_JAVA_UTIL = "fullJavaUtil"; - public static final String SUPPORT_JAVA6 = "supportJava6"; - public static final String CONFIG_PACKAGE = "configPackage"; - public static final String BASE_PACKAGE = "basePackage"; - public static final String TITLE = "title"; - public static final String WITH_XML = "withXml"; - public static final String EUREKA_URI = "eurekaUri"; - public static final String ZIPKIN_URI = "zipkinUri"; - public static final String SPRINGADMIN_URI = "springBootAdminUri"; - protected String groupId = "com.prokarma"; - protected String artifactId = "pkmst-microservice"; - protected String artifactVersion = "1.0.0"; - protected String projectFolder; - - protected String projectTestFolder; - protected String sourceFolder; - protected String testFolder; - protected String basePackage = "com.prokarma.pkmst"; - protected String serviceName = "Pkmst"; - protected String configPackage = "com.prokarma.pkmst.config"; - protected boolean implicitHeaders = false; - protected boolean serializeBigDecimalAsString = false; - protected boolean withXml = false; - protected boolean fullJavaUtil; - protected String javaUtilPrefix = ""; - protected Boolean serializableModel = false; - protected String invokerPackage; - protected String title; - protected String apiDocPath = "docs/"; - protected String modelDocPath = "docs/"; - protected String eurekaUri; - protected String zipkinUri; - protected String springBootAdminUri; - - public PkmstServerCodegen() { - super(); - this.projectFolder = "src" + File.separator + "main"; - this.projectTestFolder = "src" + File.separator + "test"; - this.sourceFolder = this.projectFolder + File.separator + "java"; - this.testFolder = this.projectTestFolder + File.separator + "java"; - embeddedTemplateDir = templateDir = "pkmst"; - apiPackage = "com.prokarma.pkmst.controller"; - modelPackage = "com.prokarma.pkmst.model"; - invokerPackage = "com.prokarma.pkmst.controller"; - setReservedWordsLowerCase(Arrays.asList( - // used as internal variables, can collide with parameter names - "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", "localVarHeaderParams", - "localVarFormParams", "localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes", - "localVarContentType", "localVarAuthNames", "localReturnType", "ApiClient", "ApiException", - "ApiResponse", "Configuration", "StringUtil", - - // language reserved words - "abstract", "continue", "for", "new", "switch", "assert", "default", "if", "package", "synchronized", - "boolean", "do", "goto", "private", "this", "break", "double", "implements", "protected", "throw", - "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", - "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", - "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while", "null")); - - this.languageSpecificPrimitives = new HashSet(Arrays.asList("String", "boolean", "Boolean", "Double", - "Integer", "Long", "Float", "Object", "byte[]")); - this.instantiationTypes.put("array", "ArrayList"); - this.instantiationTypes.put("map", "HashMap"); - this.typeMapping.put("date", "Date"); - this.typeMapping.put("file", "File"); - - this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); - this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); - this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); - this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); - this.cliOptions.add(new CliOption("serviceName", "Service Name")); - this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); - this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); - this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); - this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); - // Middleware config - this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); - this.apiTestTemplateFiles.put("api_test.mustache", ".java"); - this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); - this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); - } - - private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { - // This generator uses inline classes to define enums, which breaks when - // dealing with models that have subTypes. To clean this up, we will analyze - // the parent and child models, look for enums that match, and remove - // them from the child models and leave them in the parent. - // Because the child models extend the parents, the enums will be available via - // the parent. - - // Only bother with reconciliation if the parent model has enums. - if (!parentCodegenModel.hasEnums) { - return codegenModel; - } - - // Get the properties for the parent and child models - final List parentModelCodegenProperties = parentCodegenModel.vars; - List codegenProperties = codegenModel.vars; - - // Iterate over all of the parent model properties - boolean removedChildEnum = false; - for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { - // Look for enums - if (parentModelCodegenPropery.isEnum) { - // Now that we have found an enum in the parent class, - // and search the child class for the same enum. - Iterator iterator = codegenProperties.iterator(); - while (iterator.hasNext()) { - CodegenProperty codegenProperty = iterator.next(); - if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { - // We found an enum in the child class that is - // a duplicate of the one in the parent, so remove it. - iterator.remove(); - removedChildEnum = true; - } - } - } - } - - if (removedChildEnum) { - // If we removed an entry from this model's vars, we need to ensure hasMore is - // updated - int count = 0, numVars = codegenProperties.size(); - for (CodegenProperty codegenProperty : codegenProperties) { - count += 1; - codegenProperty.hasMore = (count < numVars) ? true : false; - } - codegenModel.vars = codegenProperties; - } - return codegenModel; - } - - private static String getAccept(Operation operation) { - String accepts = null; - String defaultContentType = "application/json"; - if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (String produces : operation.getProduces()) { - if (defaultContentType.equalsIgnoreCase(produces)) { - accepts = defaultContentType; - break; - } else { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(produces); - } - } - if (accepts == null) { - accepts = sb.toString(); - } - } else { - accepts = defaultContentType; - } - - return accepts; - } - - public CodegenType getTag() { - return CodegenType.SERVER; - } - - public String getName() { - return "pkmst"; - } - - public String getHelp() { - return "Generates a Java SpringBoot Server application using the SpringFox integration." - + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; - } - - public void processOpts() { - super.processOpts(); - if (this.additionalProperties.containsKey("basePackage")) { - this.setBasePackage((String) this.additionalProperties.get("basePackage")); - this.setInvokerPackage(this.getBasePackage()); - this.apiPackage = this.getBasePackage() + ".controller"; - this.modelPackage = this.getBasePackage() + ".model"; - this.setConfigPackage(this.getBasePackage() + ".config"); - - // this.additionalProperties.put(BASE_PACKAGE, this.getBasePackage()); - } else { - this.additionalProperties.put(BASE_PACKAGE, basePackage); - this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); - this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); - this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); - this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); - } - if (this.additionalProperties.containsKey("groupId")) { - this.setGroupId((String) this.additionalProperties.get("groupId")); - } else { - // not set, use to be passed to template - additionalProperties.put(CodegenConstants.GROUP_ID, groupId); - } - if (this.additionalProperties.containsKey("artifactId")) { - this.setArtifactId((String) this.additionalProperties.get("artifactId")); - } else { - // not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); - } - if (this.additionalProperties.containsKey("artifactVersion")) { - this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); - } else { - // not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); - } - if (this.additionalProperties.containsKey("serviceName")) { - this.setServiceName((String) this.additionalProperties.get("serviceName")); - } else { - // not set, use to be passed to template - additionalProperties.put("serviceName", serviceName); - } - - if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { - this.setSerializeBigDecimalAsString(Boolean.valueOf( - this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); - } - if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { - this.setSerializableModel( - Boolean.valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); - } - if (this.additionalProperties.containsKey(TITLE)) { - this.setTitle((String) this.additionalProperties.get(TITLE)); - } - this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); - if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { - this.setFullJavaUtil(Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); - } - - if (this.additionalProperties.containsKey(EUREKA_URI)) { - this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); - } - if (this.additionalProperties.containsKey(ZIPKIN_URI)) { - this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); - } - if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { - this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); - } - if (fullJavaUtil) { - javaUtilPrefix = "java.util."; - } - this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); - this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); - this.additionalProperties.put(SUPPORT_JAVA6, false); - this.additionalProperties.put("java8", true); - - if (this.additionalProperties.containsKey(WITH_XML)) { - this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); - } - this.additionalProperties.put(WITH_XML, withXml); - - // make api and model doc path available in mustache template - this.additionalProperties.put("apiDocPath", apiDocPath); - this.additionalProperties.put("modelDocPath", modelDocPath); - - this.importMapping.put("List", "java.util.List"); - - if (fullJavaUtil) { - this.typeMapping.put("array", "java.util.List"); - this.typeMapping.put("map", "java.util.Map"); - this.typeMapping.put("DateTime", "java.util.Date"); - this.typeMapping.put("UUID", "java.util.UUID"); - this.typeMapping.remove("List"); - this.importMapping.remove("Date"); - this.importMapping.remove("Map"); - this.importMapping.remove("HashMap"); - this.importMapping.remove("Array"); - this.importMapping.remove("ArrayList"); - this.importMapping.remove("List"); - this.importMapping.remove("Set"); - this.importMapping.remove("DateTime"); - this.importMapping.remove("UUID"); - this.instantiationTypes.put("array", "java.util.ArrayList"); - this.instantiationTypes.put("map", "java.util.HashMap"); - } - // optional jackson mappings for BigDecimal support - this.importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); - this.importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); - - // imports for pojos - this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); - this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); - this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); - this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); - this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); - this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); - this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); - this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); - this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); - this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); - this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); - this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); - this.importMapping.put("IOException", "java.io.IOException"); - this.importMapping.put("Objects", "java.util.Objects"); - this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); - // import JsonCreator if JsonProperty is imported - // used later in recursive import in postProcessingModels - this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", - "com.fasterxml.jackson.annotation.JsonCreator"); - - this.apiTemplateFiles.put("api.mustache", ".java"); - this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); - - this.modelTemplateFiles.put("model.mustache", ".java"); - - this.supportingFiles.add(new SupportingFile("SpringBootApplication.mustache", - (this.getSourceFolder() + File.separator + this.getBasePackage()).replace(".", File.separator), - this.getServiceName() + "Application" + ".java")); - - this.supportingFiles - .add(new SupportingFile("config" + File.separator + "swaggerDocumentationConfig.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", - java.io.File.separator) + File.separator + "swagger", - "SwaggerDocumentationConfig.java")); - - this.supportingFiles.add(new SupportingFile("config" + File.separator + "pkmstproperties.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) - + File.separator + "swagger", - "PkmstProperties.java")); - this.supportingFiles.add(new SupportingFile("config" + File.separator + "appconfig.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) - + File.separator, - "AppConfig.java")); - - // Security - this.supportingFiles - .add(new SupportingFile("security" + File.separator + "authorizationServerConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "AuthorizationServerConfiguration.java")); - this.supportingFiles - .add(new SupportingFile("security" + File.separator + "oAuth2SecurityConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "OAuth2SecurityConfiguration.java")); - this.supportingFiles - .add(new SupportingFile("security" + File.separator + "resourceServerConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "ResourceServerConfiguration.java")); - - // logging - - this.supportingFiles.add(new SupportingFile("logging" + File.separator + "httpLoggingFilter.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + File.separator - + "logging", - "HttpLoggingFilter.java")); - - // Resources - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-local.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "application-local.yml")); - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "application-dev.yml")); - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev-config.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "application-dev-config.yml")); - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "bootstrap.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "bootstrap.yml")); - - // POM - this.supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); - - // Readme - this.supportingFiles.add(new SupportingFile("readme.mustache", "", "Readme.md")); - - // manifest - - this.supportingFiles.add(new SupportingFile("manifest.mustache", "", "manifest.yml")); - - // docker - this.supportingFiles.add(new SupportingFile("docker.mustache", "", "Dockerfile")); - - // logstash - - this.supportingFiles.add(new SupportingFile("logstash.mustache", "", "logstash.conf")); - - // Cucumber - this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "executeReport.mustache", - this.testFolder + File.separator + this.basePackage.replace(".", File.separator) + File.separator - + "cucumber" + File.separator + "report", - "ExecuteReport.java")); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "cucumberTest.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", - serviceName + "Test.java")); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "cucumberSteps.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", - serviceName + "Steps.java")); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "package.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", - serviceName + "package-info.java")); - - // test resources - this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "cucumber.mustache", - (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "cucumber", - serviceName + ".feature")); - - this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "bootstrap.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "bootstrap.yml")); - this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "application.properties")); - this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application-test.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "application-test.properties")); - - // Gatling - this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "gatling.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "gatling.conf")); - - this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "application.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "application.conf")); - - this.supportingFiles.add(new SupportingFile( - "gatling" + File.separator + "testapi.mustache", ("src") + File.separator + ("test") + File.separator - + ("scala") + File.separator + ("scalaFiles").replace(".", java.io.File.separator), - "testapi.scala")); - - /* - * this.supportingFiles.add(new SupportingFile( "gatling" + File.separator + - * "package.mustache", ("src")+ File.separator + ("test")+ File.separator + - * ("scala")+ File.separator + ("scalaFiles").replace(".", - * java.io.File.separator), "package.info")); - */ - - // adding class for integration test - this.supportingFiles.add(new SupportingFile( - "integration" + File.separator + "integrationtest.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "controller", - serviceName + "IT.java")); - } - - @Override - public Map postProcessOperations(Map objs) { - Map operations = (Map) objs.get("operations"); - if (operations != null) { - List ops = (List) operations.get("operation"); - for (final CodegenOperation operation : ops) { - List responses = operation.responses; - if (responses != null) { - for (final CodegenResponse resp : responses) { - if ("0".equals(resp.code)) { - resp.code = "200"; - } - doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { - - public void setReturnType(final String returnType) { - resp.dataType = returnType; - } - - public void setReturnContainer(final String returnContainer) { - resp.containerType = returnContainer; - } - }); - } - } - - doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { - - public void setReturnType(final String returnType) { - operation.returnType = returnType; - } - - public void setReturnContainer(final String returnContainer) { - operation.returnContainer = returnContainer; - } - }); - - if (implicitHeaders) { - removeHeadersFromAllParams(operation.allParams); - } - } - } - - return objs; - } - - /** - * This method removes header parameters from the list of parameters and also - * corrects last allParams hasMore state. - * - * @param allParams - * list of all parameters - */ - private void removeHeadersFromAllParams(List allParams) { - if (allParams.isEmpty()) { - return; - } - final ArrayList copy = new ArrayList(allParams); - allParams.clear(); - - for (CodegenParameter p : copy) { - if (!p.isHeaderParam) { - allParams.add(p); - } - } - allParams.get(allParams.size() - 1).hasMore = false; - } - - /** - * @param returnType - * The return type that needs to be converted - * @param dataTypeAssigner - * An object that will assign the data to the respective fields in - * the model. - */ - private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { - final String rt = returnType; - if (rt == null) { - dataTypeAssigner.setReturnType("Void"); - } else if (rt.startsWith("List")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); - dataTypeAssigner.setReturnContainer("List"); - } - } else if (rt.startsWith("Map")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); - dataTypeAssigner.setReturnContainer("Map"); - } - } else if (rt.startsWith("Set")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); - dataTypeAssigner.setReturnContainer("Set"); - } - } - } - - @Override - public String getSwaggerType(Property p) { - String swaggerType = super.getSwaggerType(p); - - swaggerType = getAlias(swaggerType); - - // don't apply renaming on types from the typeMapping - if (this.typeMapping.containsKey(swaggerType)) { - return this.typeMapping.get(swaggerType); - } - - if (null == swaggerType) { - LOGGER.error("No Type defined for Property " + p); - } - return toModelName(swaggerType); - } - - @Override - public String getAlias(String name) { - if (typeAliases.containsKey(name)) { - return typeAliases.get(name); - } - return name; - } - - @Override - public String toModelName(final String name) { - // We need to check if import-mapping has a different model for this class, so - // we use it - // instead of the auto-generated one. - if (this.importMapping.containsKey(name)) { - return this.importMapping.get(name); - } - - final String sanitizedName = sanitizeName(name); - - String nameWithPrefixSuffix = sanitizedName; - if (!StringUtils.isEmpty(modelNamePrefix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; - } - - if (!StringUtils.isEmpty(modelNameSuffix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; - } - - // camelize the model name - // phone_number => PhoneNumber - final String camelizedName = camelize(nameWithPrefixSuffix); - - // model name cannot use reserved keyword, e.g. return - if (isReservedWord(camelizedName)) { - final String modelName = "Model" + camelizedName; - LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); - return modelName; - } - - // model name starts with number - if (camelizedName.matches("^\\d.*")) { - final String modelName = "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize) - LOGGER.warn( - name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName); - return modelName; - } - - return camelizedName; - } - - @Override - public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - if (serializeBigDecimalAsString) { - if (property.baseType.equals("BigDecimal")) { - // we serialize BigDecimal as `string` to avoid precision loss - property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); - - // this requires some more imports to be added for this model... - model.imports.add("ToStringSerializer"); - model.imports.add("JsonSerialize"); - } - } - - if (!fullJavaUtil) { - if ("array".equals(property.containerType)) { - model.imports.add("ArrayList"); - } else if ("map".equals(property.containerType)) { - model.imports.add("HashMap"); - } - } - - if (!BooleanUtils.toBoolean(model.isEnum)) { - // needed by all pojos, but not enums - model.imports.add("ApiModelProperty"); - model.imports.add("ApiModel"); - } - - // super.postProcessModelProperty(model, property); - - if ("null".equals(property.example)) { - property.example = null; - } - - // Add imports for Jackson - if (!Boolean.TRUE.equals(model.isEnum)) { - model.imports.add("JsonProperty"); - - if (Boolean.TRUE.equals(model.hasEnums)) { - model.imports.add("JsonValue"); - } - } else { // enum class - // Needed imports for Jackson's JsonCreator - if (this.additionalProperties.containsKey("jackson")) { - model.imports.add("JsonCreator"); - } - } - } - - @Override - public Map postProcessModelsEnum(Map objs) { - objs = super.postProcessModelsEnum(objs); - - // Add imports for Jackson - List> imports = (List>) objs.get("imports"); - List models = (List) objs.get("models"); - for (Object _mo : models) { - Map mo = (Map) _mo; - CodegenModel cm = (CodegenModel) mo.get("model"); - // for enum model - if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { - cm.imports.add(this.importMapping.get("JsonValue")); - Map item = new HashMap(); - item.put("import", this.importMapping.get("JsonValue")); - imports.add(item); - } - } - - return objs; - } - - @Override - public CodegenModel fromModel(String name, Model model, Map allDefinitions) { - CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); - if (codegenModel.description != null) { - codegenModel.imports.add("ApiModel"); - } - if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { - codegenModel.imports.add("JsonSubTypes"); - codegenModel.imports.add("JsonTypeInfo"); - } - if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { - final Model parentModel = allDefinitions.get(codegenModel.parentSchema); - final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); - codegenModel = PkmstServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); - } - return codegenModel; - } - - @Override - public Map postProcessSupportingFileData(Map objs) { - return objs; - } - - @Override - public Map postProcessModels(Map objs) { - // recursively add import for mapping one type to multiple imports - List> recursiveImports = (List>) objs.get("imports"); - if (recursiveImports == null) { - return objs; - } - - ListIterator> listIterator = recursiveImports.listIterator(); - while (listIterator.hasNext()) { - String _import = listIterator.next().get("import"); - // if the import package happens to be found in the importMapping (key) - // add the corresponding import package to the list - if (importMapping.containsKey(_import)) { - Map newImportMap = new HashMap(); - newImportMap.put("import", importMapping.get(_import)); - listIterator.add(newImportMap); - } - } - - return postProcessModelsEnum(objs); - } - - @Override - public void preprocessSwagger(Swagger swagger) { - super.preprocessSwagger(swagger); - if (swagger == null || swagger.getPaths() == null) { - return; - } - if (swagger.getTags() != null) { - System.out.println("Tags are::" + swagger.getTags()); - List resourcePaths = new ArrayList(); - for (Tag tag : swagger.getTags()) { - ResourcePath resourcePath = new ResourcePath(); - resourcePath.setPath(tag.getName()); - resourcePaths.add(resourcePath); - } - this.additionalProperties.put("resourcePaths", resourcePaths); - } - // get vendor extensions - - Map vendorExt = swagger.getInfo().getVendorExtensions(); - if (vendorExt != null && !vendorExt.toString().equals("")) { - if (vendorExt.containsKey("x-codegen")) { - - Map uris = (Map) vendorExt.get("x-codegen"); - if (uris.containsKey("eurekaUri")) { - String eurekaUri = uris.get("eurekaUri"); - additionalProperties.put(EUREKA_URI, eurekaUri); - } - if (uris.containsKey("zipkinUri")) { - String zipkinUri = uris.get("zipkinUri"); - additionalProperties.put(ZIPKIN_URI, zipkinUri); - } - if (uris.containsKey("springBootAdminUri")) { - String springBootAdminUri = uris.get("springBootAdminUri"); - additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); - } - if (uris.containsKey("pkmstInterceptor")) { - String pkmstInterceptor = uris.get("pkmstInterceptor"); - additionalProperties.put("pkmstInterceptor", pkmstInterceptor); - } - } - } - - for (String pathname : swagger.getPaths().keySet()) { - Path path = swagger.getPath(pathname); - if (path.getOperations() == null) { - continue; - } - for (Operation operation : path.getOperations()) { - boolean hasFormParameters = false; - for (Parameter parameter : operation.getParameters()) { - if (parameter instanceof FormParameter) { - hasFormParameters = true; - } - } - // only add content-Type if its no a GET-Method - if (path.getGet() != null || !operation.equals(path.getGet())) { - String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" - : "application/json"; - String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() - ? defaultContentType - : operation.getConsumes().get(0); - operation.setVendorExtension("x-contentType", contentType); - } - String accepts = getAccept(operation); - operation.setVendorExtension("x-accepts", accepts); - } - } - - if ("/".equals(swagger.getBasePath())) { - swagger.setBasePath(""); - } - - if (!additionalProperties.containsKey(TITLE)) { - // From the title, compute a reasonable name for the package and the API - String title = swagger.getInfo().getTitle(); - - // Drop any API suffix - if (title != null) { - title = title.trim().replace(" ", "-"); - if (title.toUpperCase().endsWith("API")) { - title = title.substring(0, title.length() - 3); - } - - this.title = camelize(sanitizeName(title), true); - } - additionalProperties.put(TITLE, this.title); - } - - String host = swagger.getHost(); - String port = "8008"; - if (host != null) { - String[] parts = host.split(":"); - if (parts.length > 1) { - port = parts[1]; - } - } - - this.additionalProperties.put("serverPort", port); - if (swagger.getPaths() != null) { - for (String pathname : swagger.getPaths().keySet()) { - Path path = swagger.getPath(pathname); - if (path.getOperations() != null) { - for (Operation operation : path.getOperations()) { - if (operation.getTags() != null) { - List> tags = new ArrayList>(); - for (String tag : operation.getTags()) { - Map value = new HashMap(); - value.put("tag", tag); - value.put("hasMore", "true"); - tags.add(value); - } - if (tags.size() > 0) { - tags.get(tags.size() - 1).remove("hasMore"); - } - if (operation.getTags().size() > 0) { - String tag = operation.getTags().get(0); - operation.setTags(Arrays.asList(tag)); - } - operation.setVendorExtension("x-tags", tags); - } - } - } - } - } - } - - @Override - public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, - Map> operations) { - String basePath = resourcePath; - if (basePath.startsWith("/")) { - basePath = basePath.substring(1); - } - int pos = basePath.indexOf("/"); - if (pos > 0) { - basePath = basePath.substring(0, pos); - } - - if (basePath.equals("")) { - basePath = "default"; - } else { - co.subresourceOperation = !co.path.isEmpty(); - } - List opList = operations.get(basePath); - if (opList == null) { - opList = new ArrayList(); - operations.put(basePath, opList); - } - opList.add(co); - co.baseName = basePath; - } - - @Override - public String toApiName(String name) { - if (name.length() == 0) { - return "DefaultApi"; - } - name = sanitizeName(name); - return camelize(name) + "Api"; - } - - @Override - public void setParameterExampleValue(CodegenParameter p) { - String type = p.baseType; - if (type == null) { - type = p.dataType; - } - - if ("File".equals(type)) { - String example; - - if (p.defaultValue == null) { - example = p.example; - } else { - example = p.defaultValue; - } - - if (example == null) { - example = "/path/to/file"; - } - example = "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText(example) - + "\"))"; - p.example = example; - } else { - super.setParameterExampleValue(p); - } - } - - @Override - public String escapeReservedWord(String name) { - if (this.reservedWordsMappings().containsKey(name)) { - return this.reservedWordsMappings().get(name); - } - return "_" + name; - } - - @Override - public String apiFileFolder() { - return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); - } - - @Override - public String apiTestFileFolder() { - return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); - } - - @Override - public String modelFileFolder() { - return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); - } - - @Override - public String apiDocFileFolder() { - return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); - } - - @Override - public String modelDocFileFolder() { - return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); - } - - @Override - public String toVarName(String name) { - // sanitize name - name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods - // parameters as 'final'. - - if (name.toLowerCase().matches("^_*class$")) { - return "propertyClass"; - } - - if ("_".equals(name)) { - name = "_u"; - } - - // if it's all uppper case, do nothing - if (name.matches("^[A-Z_]*$")) { - return name; - } - - if (startsWithTwoUppercaseLetters(name)) { - name = name.substring(0, 2).toLowerCase() + name.substring(2); - } - - // camelize (lower first character) the variable name - // pet_id => petId - name = camelize(name, true); - - // for reserved word or word starting with number, append _ - if (isReservedWord(name) || name.matches("^\\d.*")) { - name = escapeReservedWord(name); - } - - return name; - } - - @Override - public String toParamName(String name) { - // to avoid conflicts with 'callback' parameter for async call - if ("callback".equals(name)) { - return "paramCallback"; - } - - // should be the same as variable name - return toVarName(name); - } - - @Override - public String toModelFilename(String name) { - // should be the same as the model name - return toModelName(name); - } - - @Override - public String getTypeDeclaration(Property p) { - if (p instanceof ArrayProperty) { - ArrayProperty ap = (ArrayProperty) p; - Property inner = ap.getItems(); - if (inner == null) { - LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning null - return null; - } - return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; - } else if (p instanceof MapProperty) { - MapProperty mp = (MapProperty) p; - Property inner = mp.getAdditionalProperties(); - if (inner == null) { - LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning null - return null; - } - return getSwaggerType(p) + ""; - } - return super.getTypeDeclaration(p); - } - - @Override - public String toDefaultValue(Property p) { - if (p instanceof ArrayProperty) { - final ArrayProperty ap = (ArrayProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.ArrayList<%s>()"; - } else { - pattern = "new ArrayList<%s>()"; - } - if (ap.getItems() == null) { - return null; - } - - return String.format(pattern, getTypeDeclaration(ap.getItems())); - } else if (p instanceof MapProperty) { - final MapProperty ap = (MapProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.HashMap<%s>()"; - } else { - pattern = "new HashMap<%s>()"; - } - if (ap.getAdditionalProperties() == null) { - return null; - } - - return String.format(pattern, - String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); - } else if (p instanceof IntegerProperty) { - IntegerProperty dp = (IntegerProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - return "null"; - } else if (p instanceof LongProperty) { - LongProperty dp = (LongProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "l"; - } - return "null"; - } else if (p instanceof DoubleProperty) { - DoubleProperty dp = (DoubleProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "d"; - } - return "null"; - } else if (p instanceof FloatProperty) { - FloatProperty dp = (FloatProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "f"; - } - return "null"; - } else if (p instanceof BooleanProperty) { - BooleanProperty bp = (BooleanProperty) p; - if (bp.getDefault() != null) { - return bp.getDefault().toString(); - } - return "null"; - } else if (p instanceof StringProperty) { - StringProperty sp = (StringProperty) p; - if (sp.getDefault() != null) { - String _default = sp.getDefault(); - if (sp.getEnum() == null) { - return "\"" + escapeText(_default) + "\""; - } else { - // convert to enum var name later in postProcessModels - return _default; - } - } - return "null"; - } - return super.toDefaultValue(p); - } - - @Override - public String toExampleValue(Property p) { - if (p.getExample() != null) { - return escapeText(p.getExample().toString()); - } else { - return super.toExampleValue(p); - } - } - - @Override - public String toOperationId(String operationId) { - // throw exception if method name is empty - if (StringUtils.isEmpty(operationId)) { - throw new RuntimeException("Empty method/operation name (operationId) not allowed"); - } - - operationId = camelize(sanitizeName(operationId), true); - - // method name cannot use reserved keyword, e.g. return - if (isReservedWord(operationId)) { - String newOperationId = camelize("call_" + operationId, true); - LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); - return newOperationId; - } - - return operationId; - } - - @Override - protected boolean needToImport(String type) { - return super.needToImport(type) && type.indexOf(".") < 0; - } - - @Override - public String toEnumName(CodegenProperty property) { - return sanitizeName(camelize(property.name)) + "Enum"; - } - - @Override - public String toEnumVarName(String value, String datatype) { - if (value.length() == 0) { - return "EMPTY"; - } - - // for symbol, e.g. $, # - if (getSymbolName(value) != null) { - return getSymbolName(value).toUpperCase(); - } - - // number - if ("Integer".equals(datatype) || "Long".equals(datatype) || "Float".equals(datatype) - || "Double".equals(datatype)) { - String varName = "NUMBER_" + value; - varName = varName.replace("-", "MINUS_"); - varName = varName.replace("\\+", "PLUS_"); - varName = varName.replace("\\.", "_DOT_"); - return varName; - } - - // string - String var = value.replace("\\W+", "_").toUpperCase(); - if (var.matches("\\d.*")) { - return "_" + var; - } else { - return var; - } - } - - @Override - public String toEnumValue(String value, String datatype) { - if ("Integer".equals(datatype) || "Long".equals(datatype) || "Double".equals(datatype)) { - return value; - } else if ("Float".equals(datatype)) { - // add f to number, e.g. 3.14 => 3.14f - return value + "f"; - } else { - return "\"" + escapeText(value) + "\""; - } - } - - @Override - public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, - Map definitions, Swagger swagger) { - CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); - op.path = sanitizePath(op.path); - return op; - } - - @Override - public String escapeQuotationMark(String input) { - // remove " to avoid code injection - return input.replace("\"", ""); - } - - @Override - public String escapeUnsafeCharacters(String input) { - return input.replace("*/", "*_/").replace("/*", "/_*"); - } - - public boolean convertPropertyToBoolean(String propertyKey) { - boolean booleanValue = false; - if (additionalProperties.containsKey(propertyKey)) { - booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); - } - - return booleanValue; - } - - public String toRegularExpression(String pattern) { - return escapeText(pattern); - } - - @Override - public String sanitizeTag(String tag) { - return camelize(sanitizeName(tag)); - } - - public String toBooleanGetter(String name) { - return "is" + getterAndSetterCapitalize(name); - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getArtifactId() { - return artifactId; - } - - public void setArtifactId(String artifactId) { - this.artifactId = artifactId; - } - - public String getArtifactVersion() { - return artifactVersion; - } - - public void setArtifactVersion(String artifactVersion) { - this.artifactVersion = artifactVersion; - } - - public String getProjectFolder() { - return projectFolder; - } - - public void setProjectFolder(String projectFolder) { - this.projectFolder = projectFolder; - } - - public String getEurekaUri() { - return eurekaUri; - } - - public void setEurekaUri(String eurekaUri) { - this.eurekaUri = eurekaUri; - } - - public String getZipkinUri() { - return zipkinUri; - } - - public void setZipkinUri(String zipkinUri) { - this.zipkinUri = zipkinUri; - } - - public String getSpringBootAdminUri() { - return springBootAdminUri; - } - - public void setSpringBootAdminUri(String springBootAdminUri) { - this.springBootAdminUri = springBootAdminUri; - } - - public String getProjectTestFolder() { - return projectTestFolder; - } - - public void setProjectTestFolder(String projectTestFolder) { - this.projectTestFolder = projectTestFolder; - } - - public String getSourceFolder() { - return sourceFolder; - } - - public void setSourceFolder(String sourceFolder) { - this.sourceFolder = sourceFolder; - } - - public String getTestFolder() { - return testFolder; - } - - public void setTestFolder(String testFolder) { - this.testFolder = testFolder; - } - - public String getBasePackage() { - return basePackage; - } - - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - } - - public String getServiceName() { - return serviceName; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public String getConfigPackage() { - return configPackage; - } - - public void setConfigPackage(String configPackage) { - this.configPackage = configPackage; - } - - public boolean isImplicitHeaders() { - return implicitHeaders; - } - - public void setImplicitHeaders(boolean implicitHeaders) { - this.implicitHeaders = implicitHeaders; - } - - public boolean isSerializeBigDecimalAsString() { - return serializeBigDecimalAsString; - } - - public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { - this.serializeBigDecimalAsString = serializeBigDecimalAsString; - } - - public boolean isFullJavaUtil() { - return fullJavaUtil; - } - - public void setFullJavaUtil(boolean fullJavaUtil) { - this.fullJavaUtil = fullJavaUtil; - } - - public Boolean getSerializableModel() { - return serializableModel; - } - - public void setSerializableModel(Boolean serializableModel) { - this.serializableModel = serializableModel; - } - - public String getInvokerPackage() { - return invokerPackage; - } - - public void setInvokerPackage(String invokerPackage) { - this.invokerPackage = invokerPackage; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public boolean isWithXml() { - return withXml; - } - - public void setWithXml(boolean withXml) { - this.withXml = withXml; - } - - private boolean startsWithTwoUppercaseLetters(String name) { - boolean startsWithTwoUppercaseLetters = false; - if (name.length() > 1) { - startsWithTwoUppercaseLetters = name.substring(0, 2).equals(name.substring(0, 2).toUpperCase()); - } - return startsWithTwoUppercaseLetters; - } - - private String sanitizePath(String p) { - // prefer replace a ", instead of a fuLL URL encode for readability - return p.replace("\"", "%22"); - } - - private interface DataTypeAssigner { - - void setReturnType(String returnType); - - void setReturnContainer(String returnContainer); - } - - private class ResourcePath { - - private String path; - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - @Override - public String toString() { - return this.path; - } - } -} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 6e77a191262..38ab874450a 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -33,6 +33,7 @@ io.swagger.codegen.languages.JavaJAXRSSpecServerCodegen io.swagger.codegen.languages.JavaJerseyServerCodegen io.swagger.codegen.languages.JavaJerseyServerCodegen io.swagger.codegen.languages.JavaMSF4JServerCodegen +io.swagger.codegen.languages.JavaPKMSTServerCodegen io.swagger.codegen.languages.JavaPlayFrameworkCodegen io.swagger.codegen.languages.JavaResteasyEapServerCodegen io.swagger.codegen.languages.JavaResteasyServerCodegen @@ -47,7 +48,6 @@ io.swagger.codegen.languages.NodeJSServerCodegen io.swagger.codegen.languages.ObjcClientCodegen io.swagger.codegen.languages.PerlClientCodegen io.swagger.codegen.languages.PhpClientCodegen -io.swagger.codegen.languages.PkmstServerCodegen io.swagger.codegen.languages.PowerShellClientCodegen io.swagger.codegen.languages.PistacheServerCodegen io.swagger.codegen.languages.PythonClientCodegen diff --git a/modules/swagger-codegen/src/main/resources/pkmst/typeInfoAnnotation.mustache b/modules/swagger-codegen/src/main/resources/pkmst/typeInfoAnnotation.mustache new file mode 100644 index 00000000000..2d7983d0101 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/typeInfoAnnotation.mustache @@ -0,0 +1,7 @@ +{{#jackson}} +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{discriminator}}", visible = true ) +@JsonSubTypes({ + {{#children}} + @JsonSubTypes.Type(value = {{classname}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), + {{/children}} +}){{/jackson}} From 860e873216957abf22f0bd3829141b7dacb8d2dc Mon Sep 17 00:00:00 2001 From: sanshuman Date: Tue, 5 Dec 2017 23:38:07 +0530 Subject: [PATCH 11/19] removed tabs --- .../languages/JavaPKMSTServerCodegen.java | 2786 ++++++++--------- 1 file changed, 1393 insertions(+), 1393 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java index 0e9295d2126..174467a8ef1 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java @@ -46,1427 +46,1427 @@ */ public class JavaPKMSTServerCodegen extends DefaultCodegen implements CodegenConfig { - public static final String FULL_JAVA_UTIL = "fullJavaUtil"; - public static final String SUPPORT_JAVA6 = "supportJava6"; - public static final String CONFIG_PACKAGE = "configPackage"; - public static final String BASE_PACKAGE = "basePackage"; - public static final String TITLE = "title"; - public static final String WITH_XML = "withXml"; - public static final String EUREKA_URI = "eurekaUri"; - public static final String ZIPKIN_URI = "zipkinUri"; - public static final String SPRINGADMIN_URI = "springBootAdminUri"; - protected String groupId = "com.prokarma"; - protected String artifactId = "pkmst-microservice"; - protected String artifactVersion = "1.0.0"; - protected String projectFolder; - - protected String projectTestFolder; - protected String sourceFolder; - protected String testFolder; - protected String basePackage = "com.prokarma.pkmst"; - protected String serviceName = "Pkmst"; - protected String configPackage = "com.prokarma.pkmst.config"; - protected boolean implicitHeaders = false; - protected boolean serializeBigDecimalAsString = false; - protected boolean withXml = false; - protected boolean fullJavaUtil; - protected String javaUtilPrefix = ""; - protected Boolean serializableModel = false; - protected String invokerPackage; - protected String title; - protected String apiDocPath = "docs/"; - protected String modelDocPath = "docs/"; - protected String eurekaUri; - protected String zipkinUri; - protected String springBootAdminUri; - - public JavaPKMSTServerCodegen() { - super(); - this.projectFolder = "src" + File.separator + "main"; - this.projectTestFolder = "src" + File.separator + "test"; - this.sourceFolder = this.projectFolder + File.separator + "java"; - this.testFolder = this.projectTestFolder + File.separator + "java"; - embeddedTemplateDir = templateDir = "pkmst"; - apiPackage = "com.prokarma.pkmst.controller"; - modelPackage = "com.prokarma.pkmst.model"; - invokerPackage = "com.prokarma.pkmst.controller"; - setReservedWordsLowerCase(Arrays.asList( - // used as internal variables, can collide with parameter names - "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", "localVarHeaderParams", - "localVarFormParams", "localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes", - "localVarContentType", "localVarAuthNames", "localReturnType", "ApiClient", "ApiException", - "ApiResponse", "Configuration", "StringUtil", - - // language reserved words - "abstract", "continue", "for", "new", "switch", "assert", "default", "if", "package", "synchronized", - "boolean", "do", "goto", "private", "this", "break", "double", "implements", "protected", "throw", - "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", - "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", - "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while", "null")); - - this.languageSpecificPrimitives = new HashSet(Arrays.asList("String", "boolean", "Boolean", "Double", - "Integer", "Long", "Float", "Object", "byte[]")); - this.instantiationTypes.put("array", "ArrayList"); - this.instantiationTypes.put("map", "HashMap"); - this.typeMapping.put("date", "Date"); - this.typeMapping.put("file", "File"); - - this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); - this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); - this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); - this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); - this.cliOptions.add(new CliOption("serviceName", "Service Name")); - this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); - this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); - this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); - this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); - // Middleware config - this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); - this.apiTestTemplateFiles.put("api_test.mustache", ".java"); - this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); - this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); - } - - private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { - // This generator uses inline classes to define enums, which breaks when - // dealing with models that have subTypes. To clean this up, we will - // analyze - // the parent and child models, look for enums that match, and remove - // them from the child models and leave them in the parent. - // Because the child models extend the parents, the enums will be - // available via - // the parent. - - // Only bother with reconciliation if the parent model has enums. - if (!parentCodegenModel.hasEnums) { - return codegenModel; - } - - // Get the properties for the parent and child models - final List parentModelCodegenProperties = parentCodegenModel.vars; - List codegenProperties = codegenModel.vars; - - // Iterate over all of the parent model properties - boolean removedChildEnum = false; - for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { - // Look for enums - if (parentModelCodegenPropery.isEnum) { - // Now that we have found an enum in the parent class, - // and search the child class for the same enum. - Iterator iterator = codegenProperties.iterator(); - while (iterator.hasNext()) { - CodegenProperty codegenProperty = iterator.next(); - if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { - // We found an enum in the child class that is - // a duplicate of the one in the parent, so remove it. - iterator.remove(); - removedChildEnum = true; - } - } - } - } - - if (removedChildEnum) { - // If we removed an entry from this model's vars, we need to ensure - // hasMore is - // updated - int count = 0, numVars = codegenProperties.size(); - for (CodegenProperty codegenProperty : codegenProperties) { - count += 1; - codegenProperty.hasMore = (count < numVars) ? true : false; - } - codegenModel.vars = codegenProperties; - } - return codegenModel; - } - - private static String getAccept(Operation operation) { - String accepts = null; - String defaultContentType = "application/json"; - if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (String produces : operation.getProduces()) { - if (defaultContentType.equalsIgnoreCase(produces)) { - accepts = defaultContentType; - break; - } else { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(produces); - } - } - if (accepts == null) { - accepts = sb.toString(); - } - } else { - accepts = defaultContentType; - } - - return accepts; - } - - public CodegenType getTag() { - return CodegenType.SERVER; - } - - public String getName() { - return "pkmst"; - } - - public String getHelp() { - return "Generates a Java SpringBoot Server application using the SpringFox integration." - + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; - } - - public void processOpts() { - super.processOpts(); - if (this.additionalProperties.containsKey("basePackage")) { - this.setBasePackage((String) this.additionalProperties.get("basePackage")); - this.setInvokerPackage(this.getBasePackage()); - this.apiPackage = this.getBasePackage() + ".controller"; - this.modelPackage = this.getBasePackage() + ".model"; - this.setConfigPackage(this.getBasePackage() + ".config"); - - // this.additionalProperties.put(BASE_PACKAGE, - // this.getBasePackage()); - } else { - this.additionalProperties.put(BASE_PACKAGE, basePackage); - this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); - this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); - this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); - this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); - } - if (this.additionalProperties.containsKey("groupId")) { - this.setGroupId((String) this.additionalProperties.get("groupId")); - } else { - // not set, use to be passed to template - additionalProperties.put(CodegenConstants.GROUP_ID, groupId); - } - if (this.additionalProperties.containsKey("artifactId")) { - this.setArtifactId((String) this.additionalProperties.get("artifactId")); - } else { - // not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); - } - if (this.additionalProperties.containsKey("artifactVersion")) { - this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); - } else { - // not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); - } - if (this.additionalProperties.containsKey("serviceName")) { - this.setServiceName((String) this.additionalProperties.get("serviceName")); - } else { - // not set, use to be passed to template - additionalProperties.put("serviceName", serviceName); - } - - if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { - this.setSerializeBigDecimalAsString(Boolean.valueOf( - this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); - } - if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { - this.setSerializableModel( - Boolean.valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); - } - if (this.additionalProperties.containsKey(TITLE)) { - this.setTitle((String) this.additionalProperties.get(TITLE)); - } - this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); - if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { - this.setFullJavaUtil(Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); - } - - if (this.additionalProperties.containsKey(EUREKA_URI)) { - this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); - } - if (this.additionalProperties.containsKey(ZIPKIN_URI)) { - this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); - } - if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { - this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); - } - if (fullJavaUtil) { - javaUtilPrefix = "java.util."; - } - this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); - this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); - this.additionalProperties.put(SUPPORT_JAVA6, false); - this.additionalProperties.put("java8", true); - - if (this.additionalProperties.containsKey(WITH_XML)) { - this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); - } - this.additionalProperties.put(WITH_XML, withXml); - - // make api and model doc path available in mustache template - this.additionalProperties.put("apiDocPath", apiDocPath); - this.additionalProperties.put("modelDocPath", modelDocPath); - - this.importMapping.put("List", "java.util.List"); - - if (fullJavaUtil) { - this.typeMapping.put("array", "java.util.List"); - this.typeMapping.put("map", "java.util.Map"); - this.typeMapping.put("DateTime", "java.util.Date"); - this.typeMapping.put("UUID", "java.util.UUID"); - this.typeMapping.remove("List"); - this.importMapping.remove("Date"); - this.importMapping.remove("Map"); - this.importMapping.remove("HashMap"); - this.importMapping.remove("Array"); - this.importMapping.remove("ArrayList"); - this.importMapping.remove("List"); - this.importMapping.remove("Set"); - this.importMapping.remove("DateTime"); - this.importMapping.remove("UUID"); - this.instantiationTypes.put("array", "java.util.ArrayList"); - this.instantiationTypes.put("map", "java.util.HashMap"); - } - // optional jackson mappings for BigDecimal support - this.importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); - this.importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); - - // imports for pojos - this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); - this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); - this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); - this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); - this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); - this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); - this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); - this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); - this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); - this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); - this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); - this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); - this.importMapping.put("IOException", "java.io.IOException"); - this.importMapping.put("Objects", "java.util.Objects"); - this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); - // import JsonCreator if JsonProperty is imported - // used later in recursive import in postProcessingModels - this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", - "com.fasterxml.jackson.annotation.JsonCreator"); - - this.apiTemplateFiles.put("api.mustache", ".java"); - this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); - - this.modelTemplateFiles.put("model.mustache", ".java"); - - this.supportingFiles.add(new SupportingFile("SpringBootApplication.mustache", - (this.getSourceFolder() + File.separator + this.getBasePackage()).replace(".", File.separator), - this.getServiceName() + "Application" + ".java")); - - this.supportingFiles - .add(new SupportingFile("config" + File.separator + "swaggerDocumentationConfig.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", - java.io.File.separator) + File.separator + "swagger", - "SwaggerDocumentationConfig.java")); - - this.supportingFiles.add(new SupportingFile("config" + File.separator + "pkmstproperties.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) - + File.separator + "swagger", - "PkmstProperties.java")); - this.supportingFiles.add(new SupportingFile("config" + File.separator + "appconfig.mustache", - (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) - + File.separator, - "AppConfig.java")); - - // Security - this.supportingFiles - .add(new SupportingFile("security" + File.separator + "authorizationServerConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "AuthorizationServerConfiguration.java")); - this.supportingFiles - .add(new SupportingFile("security" + File.separator + "oAuth2SecurityConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "OAuth2SecurityConfiguration.java")); - this.supportingFiles - .add(new SupportingFile("security" + File.separator + "resourceServerConfiguration.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "security", - "ResourceServerConfiguration.java")); - - // logging - - this.supportingFiles.add(new SupportingFile("logging" + File.separator + "httpLoggingFilter.mustache", - (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + File.separator - + "logging", - "HttpLoggingFilter.java")); - - // Resources - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-local.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "application-local.yml")); - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "application-dev.yml")); - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev-config.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "application-dev-config.yml")); - this.supportingFiles.add(new SupportingFile("resources" + File.separator + "bootstrap.mustache", - ("src.main.resources").replace(".", java.io.File.separator), "bootstrap.yml")); - - // POM - this.supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); - - // Readme - this.supportingFiles.add(new SupportingFile("readme.mustache", "", "Readme.md")); - - // manifest - - this.supportingFiles.add(new SupportingFile("manifest.mustache", "", "manifest.yml")); - - // docker - this.supportingFiles.add(new SupportingFile("docker.mustache", "", "Dockerfile")); - - // logstash - - this.supportingFiles.add(new SupportingFile("logstash.mustache", "", "logstash.conf")); - - // Cucumber - this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "executeReport.mustache", - this.testFolder + File.separator + this.basePackage.replace(".", File.separator) + File.separator - + "cucumber" + File.separator + "report", - "ExecuteReport.java")); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "cucumberTest.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", - serviceName + "Test.java")); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "cucumberSteps.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", - serviceName + "Steps.java")); - - this.supportingFiles.add(new SupportingFile( - "cucumber" + File.separator + "package.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", - serviceName + "package-info.java")); - - // test resources - this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "cucumber.mustache", - (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) - + File.separator + "cucumber", - serviceName + ".feature")); - - this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "bootstrap.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "bootstrap.yml")); - this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "application.properties")); - this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application-test.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "application-test.properties")); - - // Gatling - this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "gatling.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "gatling.conf")); - - this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "application.mustache", - ("src.test.resources").replace(".", java.io.File.separator), "application.conf")); - - this.supportingFiles.add(new SupportingFile( - "gatling" + File.separator + "testapi.mustache", ("src") + File.separator + ("test") + File.separator - + ("scala") + File.separator + ("scalaFiles").replace(".", java.io.File.separator), - "testapi.scala")); - - /* - * this.supportingFiles.add(new SupportingFile( "gatling" + - * File.separator + "package.mustache", ("src")+ File.separator + - * ("test")+ File.separator + ("scala")+ File.separator + - * ("scalaFiles").replace(".", java.io.File.separator), - * "package.info")); - */ - - // adding class for integration test - this.supportingFiles.add(new SupportingFile( - "integration" + File.separator + "integrationtest.mustache", this.testFolder + File.separator - + this.basePackage.replace(".", File.separator) + File.separator + "controller", - serviceName + "IT.java")); - } - - @Override - public Map postProcessOperations(Map objs) { - Map operations = (Map) objs.get("operations"); - if (operations != null) { - List ops = (List) operations.get("operation"); - for (final CodegenOperation operation : ops) { - List responses = operation.responses; - if (responses != null) { - for (final CodegenResponse resp : responses) { - if ("0".equals(resp.code)) { - resp.code = "200"; - } - doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { - - public void setReturnType(final String returnType) { - resp.dataType = returnType; - } - - public void setReturnContainer(final String returnContainer) { - resp.containerType = returnContainer; - } - }); - } - } - - doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { - - public void setReturnType(final String returnType) { - operation.returnType = returnType; - } - - public void setReturnContainer(final String returnContainer) { - operation.returnContainer = returnContainer; - } - }); - - if (implicitHeaders) { - removeHeadersFromAllParams(operation.allParams); - } - } - } - - return objs; - } - - /** - * This method removes header parameters from the list of parameters and - * also corrects last allParams hasMore state. - * - * @param allParams - * list of all parameters - */ - private void removeHeadersFromAllParams(List allParams) { - if (allParams.isEmpty()) { - return; - } - final ArrayList copy = new ArrayList(allParams); - allParams.clear(); - - for (CodegenParameter p : copy) { - if (!p.isHeaderParam) { - allParams.add(p); - } - } - allParams.get(allParams.size() - 1).hasMore = false; - } - - /** - * @param returnType - * The return type that needs to be converted - * @param dataTypeAssigner - * An object that will assign the data to the respective fields - * in the model. - */ - private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { - final String rt = returnType; - if (rt == null) { - dataTypeAssigner.setReturnType("Void"); - } else if (rt.startsWith("List")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); - dataTypeAssigner.setReturnContainer("List"); - } - } else if (rt.startsWith("Map")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); - dataTypeAssigner.setReturnContainer("Map"); - } - } else if (rt.startsWith("Set")) { - int end = rt.lastIndexOf(">"); - if (end > 0) { - dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); - dataTypeAssigner.setReturnContainer("Set"); - } - } - } - - @Override - public String getSwaggerType(Property p) { - String swaggerType = super.getSwaggerType(p); - - swaggerType = getAlias(swaggerType); - - // don't apply renaming on types from the typeMapping - if (this.typeMapping.containsKey(swaggerType)) { - return this.typeMapping.get(swaggerType); - } - - if (null == swaggerType) { - LOGGER.error("No Type defined for Property " + p); - } - return toModelName(swaggerType); - } - - @Override - public String getAlias(String name) { - if (typeAliases.containsKey(name)) { - return typeAliases.get(name); - } - return name; - } - - @Override - public String toModelName(final String name) { - // We need to check if import-mapping has a different model for this - // class, so - // we use it - // instead of the auto-generated one. - if (this.importMapping.containsKey(name)) { - return this.importMapping.get(name); - } - - final String sanitizedName = sanitizeName(name); - - String nameWithPrefixSuffix = sanitizedName; - if (!StringUtils.isEmpty(modelNamePrefix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; - } - - if (!StringUtils.isEmpty(modelNameSuffix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; - } - - // camelize the model name - // phone_number => PhoneNumber - final String camelizedName = camelize(nameWithPrefixSuffix); - - // model name cannot use reserved keyword, e.g. return - if (isReservedWord(camelizedName)) { - final String modelName = "Model" + camelizedName; - LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); - return modelName; - } - - // model name starts with number - if (camelizedName.matches("^\\d.*")) { - final String modelName = "Model" + camelizedName; // e.g. - // 200Response - // => - // Model200Response - // (after - // camelize) - LOGGER.warn( - name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName); - return modelName; - } - - return camelizedName; - } - - @Override - public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - if (serializeBigDecimalAsString) { - if (property.baseType.equals("BigDecimal")) { - // we serialize BigDecimal as `string` to avoid precision loss - property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); - - // this requires some more imports to be added for this model... - model.imports.add("ToStringSerializer"); - model.imports.add("JsonSerialize"); - } - } - - if (!fullJavaUtil) { - if ("array".equals(property.containerType)) { - model.imports.add("ArrayList"); - } else if ("map".equals(property.containerType)) { - model.imports.add("HashMap"); - } - } - - if (!BooleanUtils.toBoolean(model.isEnum)) { - // needed by all pojos, but not enums - model.imports.add("ApiModelProperty"); - model.imports.add("ApiModel"); - } - - // super.postProcessModelProperty(model, property); - - if ("null".equals(property.example)) { - property.example = null; - } - - // Add imports for Jackson - if (!Boolean.TRUE.equals(model.isEnum)) { - model.imports.add("JsonProperty"); - - if (Boolean.TRUE.equals(model.hasEnums)) { - model.imports.add("JsonValue"); - } - } else { // enum class - // Needed imports for Jackson's JsonCreator - if (this.additionalProperties.containsKey("jackson")) { - model.imports.add("JsonCreator"); - } - } - } - - @Override - public Map postProcessModelsEnum(Map objs) { - objs = super.postProcessModelsEnum(objs); - - // Add imports for Jackson - List> imports = (List>) objs.get("imports"); - List models = (List) objs.get("models"); - for (Object _mo : models) { - Map mo = (Map) _mo; - CodegenModel cm = (CodegenModel) mo.get("model"); - // for enum model - if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { - cm.imports.add(this.importMapping.get("JsonValue")); - Map item = new HashMap(); - item.put("import", this.importMapping.get("JsonValue")); - imports.add(item); - } - } - - return objs; - } - - @Override - public CodegenModel fromModel(String name, Model model, Map allDefinitions) { - CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); - if (codegenModel.description != null) { - codegenModel.imports.add("ApiModel"); - } - if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { - codegenModel.imports.add("JsonSubTypes"); - codegenModel.imports.add("JsonTypeInfo"); - } - if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { - final Model parentModel = allDefinitions.get(codegenModel.parentSchema); - final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); - codegenModel = JavaPKMSTServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); - } - return codegenModel; - } - - @Override - public Map postProcessSupportingFileData(Map objs) { - return objs; - } - - @Override - public Map postProcessModels(Map objs) { - // recursively add import for mapping one type to multiple imports - List> recursiveImports = (List>) objs.get("imports"); - if (recursiveImports == null) { - return objs; - } - - ListIterator> listIterator = recursiveImports.listIterator(); - while (listIterator.hasNext()) { - String _import = listIterator.next().get("import"); - // if the import package happens to be found in the importMapping - // (key) - // add the corresponding import package to the list - if (importMapping.containsKey(_import)) { - Map newImportMap = new HashMap(); - newImportMap.put("import", importMapping.get(_import)); - listIterator.add(newImportMap); - } - } - - return postProcessModelsEnum(objs); - } - - @Override - public void preprocessSwagger(Swagger swagger) { - super.preprocessSwagger(swagger); - if (swagger == null || swagger.getPaths() == null) { - return; - } - if (swagger.getTags() != null) { - System.out.println("Tags are::" + swagger.getTags()); - List resourcePaths = new ArrayList(); - for (Tag tag : swagger.getTags()) { - ResourcePath resourcePath = new ResourcePath(); - resourcePath.setPath(tag.getName()); - resourcePaths.add(resourcePath); - } - this.additionalProperties.put("resourcePaths", resourcePaths); - } - // get vendor extensions - - Map vendorExt = swagger.getInfo().getVendorExtensions(); - if (vendorExt != null && !vendorExt.toString().equals("")) { - if (vendorExt.containsKey("x-codegen")) { - - Map uris = (Map) vendorExt.get("x-codegen"); - if (uris.containsKey("eurekaUri")) { - String eurekaUri = uris.get("eurekaUri"); - additionalProperties.put(EUREKA_URI, eurekaUri); - } - if (uris.containsKey("zipkinUri")) { - String zipkinUri = uris.get("zipkinUri"); - additionalProperties.put(ZIPKIN_URI, zipkinUri); - } - if (uris.containsKey("springBootAdminUri")) { - String springBootAdminUri = uris.get("springBootAdminUri"); - additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); - } - if (uris.containsKey("pkmstInterceptor")) { - String pkmstInterceptor = uris.get("pkmstInterceptor"); - additionalProperties.put("pkmstInterceptor", pkmstInterceptor); - } - } - } - - for (String pathname : swagger.getPaths().keySet()) { - Path path = swagger.getPath(pathname); - if (path.getOperations() == null) { - continue; - } - for (Operation operation : path.getOperations()) { - boolean hasFormParameters = false; - for (Parameter parameter : operation.getParameters()) { - if (parameter instanceof FormParameter) { - hasFormParameters = true; - } - } - // only add content-Type if its no a GET-Method - if (path.getGet() != null || !operation.equals(path.getGet())) { - String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" - : "application/json"; - String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() - ? defaultContentType : operation.getConsumes().get(0); - operation.setVendorExtension("x-contentType", contentType); - } - String accepts = getAccept(operation); - operation.setVendorExtension("x-accepts", accepts); - } - } - - if ("/".equals(swagger.getBasePath())) { - swagger.setBasePath(""); - } - - if (!additionalProperties.containsKey(TITLE)) { - // From the title, compute a reasonable name for the package and the - // API - String title = swagger.getInfo().getTitle(); - - // Drop any API suffix - if (title != null) { - title = title.trim().replace(" ", "-"); - if (title.toUpperCase().endsWith("API")) { - title = title.substring(0, title.length() - 3); - } - - this.title = camelize(sanitizeName(title), true); - } - additionalProperties.put(TITLE, this.title); - } - - String host = swagger.getHost(); - String port = "8008"; - if (host != null) { - String[] parts = host.split(":"); - if (parts.length > 1) { - port = parts[1]; - } - } - - this.additionalProperties.put("serverPort", port); - if (swagger.getPaths() != null) { - for (String pathname : swagger.getPaths().keySet()) { - Path path = swagger.getPath(pathname); - if (path.getOperations() != null) { - for (Operation operation : path.getOperations()) { - if (operation.getTags() != null) { - List> tags = new ArrayList>(); - for (String tag : operation.getTags()) { - Map value = new HashMap(); - value.put("tag", tag); - value.put("hasMore", "true"); - tags.add(value); - } - if (tags.size() > 0) { - tags.get(tags.size() - 1).remove("hasMore"); - } - if (operation.getTags().size() > 0) { - String tag = operation.getTags().get(0); - operation.setTags(Arrays.asList(tag)); - } - operation.setVendorExtension("x-tags", tags); - } - } - } - } - } - } - - @Override - public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, - Map> operations) { - String basePath = resourcePath; - if (basePath.startsWith("/")) { - basePath = basePath.substring(1); - } - int pos = basePath.indexOf("/"); - if (pos > 0) { - basePath = basePath.substring(0, pos); - } - - if (basePath.equals("")) { - basePath = "default"; - } else { - co.subresourceOperation = !co.path.isEmpty(); - } - List opList = operations.get(basePath); - if (opList == null) { - opList = new ArrayList(); - operations.put(basePath, opList); - } - opList.add(co); - co.baseName = basePath; - } - - @Override - public String toApiName(String name) { - if (name.length() == 0) { - return "DefaultApi"; - } - name = sanitizeName(name); - return camelize(name) + "Api"; - } - - @Override - public void setParameterExampleValue(CodegenParameter p) { - String type = p.baseType; - if (type == null) { - type = p.dataType; - } - - if ("File".equals(type)) { - String example; - - if (p.defaultValue == null) { - example = p.example; - } else { - example = p.defaultValue; - } - - if (example == null) { - example = "/path/to/file"; - } - example = "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText(example) - + "\"))"; - p.example = example; - } else { - super.setParameterExampleValue(p); - } - } - - @Override - public String escapeReservedWord(String name) { - if (this.reservedWordsMappings().containsKey(name)) { - return this.reservedWordsMappings().get(name); - } - return "_" + name; - } - - @Override - public String apiFileFolder() { - return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); - } - - @Override - public String apiTestFileFolder() { - return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); - } - - @Override - public String modelFileFolder() { - return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); - } - - @Override - public String apiDocFileFolder() { - return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); - } - - @Override - public String modelDocFileFolder() { - return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); - } - - @Override - public String toVarName(String name) { - // sanitize name - name = sanitizeName(name); // FIXME: a parameter should not be assigned. - // Also declare the methods - // parameters as 'final'. - - if (name.toLowerCase().matches("^_*class$")) { - return "propertyClass"; - } - - if ("_".equals(name)) { - name = "_u"; - } - - // if it's all uppper case, do nothing - if (name.matches("^[A-Z_]*$")) { - return name; - } - - if (startsWithTwoUppercaseLetters(name)) { - name = name.substring(0, 2).toLowerCase() + name.substring(2); - } - - // camelize (lower first character) the variable name - // pet_id => petId - name = camelize(name, true); - - // for reserved word or word starting with number, append _ - if (isReservedWord(name) || name.matches("^\\d.*")) { - name = escapeReservedWord(name); - } - - return name; - } - - @Override - public String toParamName(String name) { - // to avoid conflicts with 'callback' parameter for async call - if ("callback".equals(name)) { - return "paramCallback"; - } - - // should be the same as variable name - return toVarName(name); - } - - @Override - public String toModelFilename(String name) { - // should be the same as the model name - return toModelName(name); - } - - @Override - public String getTypeDeclaration(Property p) { - if (p instanceof ArrayProperty) { - ArrayProperty ap = (ArrayProperty) p; - Property inner = ap.getItems(); - if (inner == null) { - LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning - // null - return null; - } - return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; - } else if (p instanceof MapProperty) { - MapProperty mp = (MapProperty) p; - Property inner = mp.getAdditionalProperties(); - if (inner == null) { - LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning - // null - return null; - } - return getSwaggerType(p) + ""; - } - return super.getTypeDeclaration(p); - } - - @Override - public String toDefaultValue(Property p) { - if (p instanceof ArrayProperty) { - final ArrayProperty ap = (ArrayProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.ArrayList<%s>()"; - } else { - pattern = "new ArrayList<%s>()"; - } - if (ap.getItems() == null) { - return null; - } - - return String.format(pattern, getTypeDeclaration(ap.getItems())); - } else if (p instanceof MapProperty) { - final MapProperty ap = (MapProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.HashMap<%s>()"; - } else { - pattern = "new HashMap<%s>()"; - } - if (ap.getAdditionalProperties() == null) { - return null; - } - - return String.format(pattern, - String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); - } else if (p instanceof IntegerProperty) { - IntegerProperty dp = (IntegerProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - return "null"; - } else if (p instanceof LongProperty) { - LongProperty dp = (LongProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "l"; - } - return "null"; - } else if (p instanceof DoubleProperty) { - DoubleProperty dp = (DoubleProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "d"; - } - return "null"; - } else if (p instanceof FloatProperty) { - FloatProperty dp = (FloatProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "f"; - } - return "null"; - } else if (p instanceof BooleanProperty) { - BooleanProperty bp = (BooleanProperty) p; - if (bp.getDefault() != null) { - return bp.getDefault().toString(); - } - return "null"; - } else if (p instanceof StringProperty) { - StringProperty sp = (StringProperty) p; - if (sp.getDefault() != null) { - String _default = sp.getDefault(); - if (sp.getEnum() == null) { - return "\"" + escapeText(_default) + "\""; - } else { - // convert to enum var name later in postProcessModels - return _default; - } - } - return "null"; - } - return super.toDefaultValue(p); - } - - @Override - public String toExampleValue(Property p) { - if (p.getExample() != null) { - return escapeText(p.getExample().toString()); - } else { - return super.toExampleValue(p); - } - } - - @Override - public String toOperationId(String operationId) { - // throw exception if method name is empty - if (StringUtils.isEmpty(operationId)) { - throw new RuntimeException("Empty method/operation name (operationId) not allowed"); - } - - operationId = camelize(sanitizeName(operationId), true); - - // method name cannot use reserved keyword, e.g. return - if (isReservedWord(operationId)) { - String newOperationId = camelize("call_" + operationId, true); - LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); - return newOperationId; - } - - return operationId; - } - - @Override - protected boolean needToImport(String type) { - return super.needToImport(type) && type.indexOf(".") < 0; - } - - @Override - public String toEnumName(CodegenProperty property) { - return sanitizeName(camelize(property.name)) + "Enum"; - } - - @Override - public String toEnumVarName(String value, String datatype) { - if (value.length() == 0) { - return "EMPTY"; - } - - // for symbol, e.g. $, # - if (getSymbolName(value) != null) { - return getSymbolName(value).toUpperCase(); - } - - // number - if ("Integer".equals(datatype) || "Long".equals(datatype) || "Float".equals(datatype) - || "Double".equals(datatype)) { - String varName = "NUMBER_" + value; - varName = varName.replace("-", "MINUS_"); - varName = varName.replace("\\+", "PLUS_"); - varName = varName.replace("\\.", "_DOT_"); - return varName; - } - - // string - String var = value.replace("\\W+", "_").toUpperCase(); - if (var.matches("\\d.*")) { - return "_" + var; - } else { - return var; - } - } - - @Override - public String toEnumValue(String value, String datatype) { - if ("Integer".equals(datatype) || "Long".equals(datatype) || "Double".equals(datatype)) { - return value; - } else if ("Float".equals(datatype)) { - // add f to number, e.g. 3.14 => 3.14f - return value + "f"; - } else { - return "\"" + escapeText(value) + "\""; - } - } - - @Override - public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, - Map definitions, Swagger swagger) { - CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); - op.path = sanitizePath(op.path); - return op; - } - - @Override - public String escapeQuotationMark(String input) { - // remove " to avoid code injection - return input.replace("\"", ""); - } - - @Override - public String escapeUnsafeCharacters(String input) { - return input.replace("*/", "*_/").replace("/*", "/_*"); - } - - public boolean convertPropertyToBoolean(String propertyKey) { - boolean booleanValue = false; - if (additionalProperties.containsKey(propertyKey)) { - booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); - } - - return booleanValue; - } - - public String toRegularExpression(String pattern) { - return escapeText(pattern); - } - - @Override - public String sanitizeTag(String tag) { - return camelize(sanitizeName(tag)); - } - - public String toBooleanGetter(String name) { - return "is" + getterAndSetterCapitalize(name); - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getArtifactId() { - return artifactId; - } - - public void setArtifactId(String artifactId) { - this.artifactId = artifactId; - } - - public String getArtifactVersion() { - return artifactVersion; - } - - public void setArtifactVersion(String artifactVersion) { - this.artifactVersion = artifactVersion; - } - - public String getProjectFolder() { - return projectFolder; - } - - public void setProjectFolder(String projectFolder) { - this.projectFolder = projectFolder; - } - - public String getEurekaUri() { - return eurekaUri; - } - - public void setEurekaUri(String eurekaUri) { - this.eurekaUri = eurekaUri; - } - - public String getZipkinUri() { - return zipkinUri; - } - - public void setZipkinUri(String zipkinUri) { - this.zipkinUri = zipkinUri; - } - - public String getSpringBootAdminUri() { - return springBootAdminUri; - } - - public void setSpringBootAdminUri(String springBootAdminUri) { - this.springBootAdminUri = springBootAdminUri; - } - - public String getProjectTestFolder() { - return projectTestFolder; - } - - public void setProjectTestFolder(String projectTestFolder) { - this.projectTestFolder = projectTestFolder; - } - - public String getSourceFolder() { - return sourceFolder; - } - - public void setSourceFolder(String sourceFolder) { - this.sourceFolder = sourceFolder; - } - - public String getTestFolder() { - return testFolder; - } - - public void setTestFolder(String testFolder) { - this.testFolder = testFolder; - } + public static final String FULL_JAVA_UTIL = "fullJavaUtil"; + public static final String SUPPORT_JAVA6 = "supportJava6"; + public static final String CONFIG_PACKAGE = "configPackage"; + public static final String BASE_PACKAGE = "basePackage"; + public static final String TITLE = "title"; + public static final String WITH_XML = "withXml"; + public static final String EUREKA_URI = "eurekaUri"; + public static final String ZIPKIN_URI = "zipkinUri"; + public static final String SPRINGADMIN_URI = "springBootAdminUri"; + protected String groupId = "com.prokarma"; + protected String artifactId = "pkmst-microservice"; + protected String artifactVersion = "1.0.0"; + protected String projectFolder; + + protected String projectTestFolder; + protected String sourceFolder; + protected String testFolder; + protected String basePackage = "com.prokarma.pkmst"; + protected String serviceName = "Pkmst"; + protected String configPackage = "com.prokarma.pkmst.config"; + protected boolean implicitHeaders = false; + protected boolean serializeBigDecimalAsString = false; + protected boolean withXml = false; + protected boolean fullJavaUtil; + protected String javaUtilPrefix = ""; + protected Boolean serializableModel = false; + protected String invokerPackage; + protected String title; + protected String apiDocPath = "docs/"; + protected String modelDocPath = "docs/"; + protected String eurekaUri; + protected String zipkinUri; + protected String springBootAdminUri; + + public JavaPKMSTServerCodegen() { + super(); + this.projectFolder = "src" + File.separator + "main"; + this.projectTestFolder = "src" + File.separator + "test"; + this.sourceFolder = this.projectFolder + File.separator + "java"; + this.testFolder = this.projectTestFolder + File.separator + "java"; + embeddedTemplateDir = templateDir = "pkmst"; + apiPackage = "com.prokarma.pkmst.controller"; + modelPackage = "com.prokarma.pkmst.model"; + invokerPackage = "com.prokarma.pkmst.controller"; + setReservedWordsLowerCase(Arrays.asList( + // used as internal variables, can collide with parameter names + "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", "localVarHeaderParams", + "localVarFormParams", "localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes", + "localVarContentType", "localVarAuthNames", "localReturnType", "ApiClient", "ApiException", + "ApiResponse", "Configuration", "StringUtil", + + // language reserved words + "abstract", "continue", "for", "new", "switch", "assert", "default", "if", "package", "synchronized", + "boolean", "do", "goto", "private", "this", "break", "double", "implements", "protected", "throw", + "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", + "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", + "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while", "null")); + + this.languageSpecificPrimitives = new HashSet(Arrays.asList("String", "boolean", "Boolean", "Double", + "Integer", "Long", "Float", "Object", "byte[]")); + this.instantiationTypes.put("array", "ArrayList"); + this.instantiationTypes.put("map", "HashMap"); + this.typeMapping.put("date", "Date"); + this.typeMapping.put("file", "File"); + + this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); + this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); + this.cliOptions.add(new CliOption("basePackage", "base package for java source code")); + this.cliOptions.add(new CliOption("serviceName", "Service Name")); + this.cliOptions.add(new CliOption(TITLE, "server title name or client service name")); + this.cliOptions.add(new CliOption("eurekaUri", "Eureka URI")); + this.cliOptions.add(new CliOption("zipkinUri", "Zipkin URI")); + this.cliOptions.add(new CliOption("springBootAdminUri", "Spring-Boot URI")); + // Middleware config + this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); + this.apiTestTemplateFiles.put("api_test.mustache", ".java"); + this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); + this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); + } + + private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { + // This generator uses inline classes to define enums, which breaks when + // dealing with models that have subTypes. To clean this up, we will + // analyze + // the parent and child models, look for enums that match, and remove + // them from the child models and leave them in the parent. + // Because the child models extend the parents, the enums will be + // available via + // the parent. + + // Only bother with reconciliation if the parent model has enums. + if (!parentCodegenModel.hasEnums) { + return codegenModel; + } + + // Get the properties for the parent and child models + final List parentModelCodegenProperties = parentCodegenModel.vars; + List codegenProperties = codegenModel.vars; + + // Iterate over all of the parent model properties + boolean removedChildEnum = false; + for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { + // Look for enums + if (parentModelCodegenPropery.isEnum) { + // Now that we have found an enum in the parent class, + // and search the child class for the same enum. + Iterator iterator = codegenProperties.iterator(); + while (iterator.hasNext()) { + CodegenProperty codegenProperty = iterator.next(); + if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { + // We found an enum in the child class that is + // a duplicate of the one in the parent, so remove it. + iterator.remove(); + removedChildEnum = true; + } + } + } + } + + if (removedChildEnum) { + // If we removed an entry from this model's vars, we need to ensure + // hasMore is + // updated + int count = 0, numVars = codegenProperties.size(); + for (CodegenProperty codegenProperty : codegenProperties) { + count += 1; + codegenProperty.hasMore = (count < numVars) ? true : false; + } + codegenModel.vars = codegenProperties; + } + return codegenModel; + } + + private static String getAccept(Operation operation) { + String accepts = null; + String defaultContentType = "application/json"; + if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String produces : operation.getProduces()) { + if (defaultContentType.equalsIgnoreCase(produces)) { + accepts = defaultContentType; + break; + } else { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(produces); + } + } + if (accepts == null) { + accepts = sb.toString(); + } + } else { + accepts = defaultContentType; + } + + return accepts; + } + + public CodegenType getTag() { + return CodegenType.SERVER; + } + + public String getName() { + return "pkmst"; + } + + public String getHelp() { + return "Generates a Java SpringBoot Server application using the SpringFox integration." + + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; + } + + public void processOpts() { + super.processOpts(); + if (this.additionalProperties.containsKey("basePackage")) { + this.setBasePackage((String) this.additionalProperties.get("basePackage")); + this.setInvokerPackage(this.getBasePackage()); + this.apiPackage = this.getBasePackage() + ".controller"; + this.modelPackage = this.getBasePackage() + ".model"; + this.setConfigPackage(this.getBasePackage() + ".config"); + + // this.additionalProperties.put(BASE_PACKAGE, + // this.getBasePackage()); + } else { + this.additionalProperties.put(BASE_PACKAGE, basePackage); + this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); + this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); + this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); + this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + } + if (this.additionalProperties.containsKey("groupId")) { + this.setGroupId((String) this.additionalProperties.get("groupId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.GROUP_ID, groupId); + } + if (this.additionalProperties.containsKey("artifactId")) { + this.setArtifactId((String) this.additionalProperties.get("artifactId")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); + } + if (this.additionalProperties.containsKey("artifactVersion")) { + this.setArtifactVersion((String) this.additionalProperties.get("artifactVersion")); + } else { + // not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + } + if (this.additionalProperties.containsKey("serviceName")) { + this.setServiceName((String) this.additionalProperties.get("serviceName")); + } else { + // not set, use to be passed to template + additionalProperties.put("serviceName", serviceName); + } + + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { + this.setSerializeBigDecimalAsString(Boolean.valueOf( + this.additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); + } + if (this.additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { + this.setSerializableModel( + Boolean.valueOf(this.additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); + } + if (this.additionalProperties.containsKey(TITLE)) { + this.setTitle((String) this.additionalProperties.get(TITLE)); + } + this.additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); + if (this.additionalProperties.containsKey(FULL_JAVA_UTIL)) { + this.setFullJavaUtil(Boolean.valueOf(this.additionalProperties.get(FULL_JAVA_UTIL).toString())); + } + + if (this.additionalProperties.containsKey(EUREKA_URI)) { + this.setEurekaUri((String) this.additionalProperties.get(EUREKA_URI)); + } + if (this.additionalProperties.containsKey(ZIPKIN_URI)) { + this.setZipkinUri((String) this.additionalProperties.get(ZIPKIN_URI)); + } + if (this.additionalProperties.containsKey(SPRINGADMIN_URI)) { + this.setSpringBootAdminUri((String) this.additionalProperties.get(SPRINGADMIN_URI)); + } + if (fullJavaUtil) { + javaUtilPrefix = "java.util."; + } + this.additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); + this.additionalProperties.put("javaUtilPrefix", javaUtilPrefix); + this.additionalProperties.put(SUPPORT_JAVA6, false); + this.additionalProperties.put("java8", true); + + if (this.additionalProperties.containsKey(WITH_XML)) { + this.setWithXml(Boolean.valueOf(additionalProperties.get(WITH_XML).toString())); + } + this.additionalProperties.put(WITH_XML, withXml); + + // make api and model doc path available in mustache template + this.additionalProperties.put("apiDocPath", apiDocPath); + this.additionalProperties.put("modelDocPath", modelDocPath); + + this.importMapping.put("List", "java.util.List"); + + if (fullJavaUtil) { + this.typeMapping.put("array", "java.util.List"); + this.typeMapping.put("map", "java.util.Map"); + this.typeMapping.put("DateTime", "java.util.Date"); + this.typeMapping.put("UUID", "java.util.UUID"); + this.typeMapping.remove("List"); + this.importMapping.remove("Date"); + this.importMapping.remove("Map"); + this.importMapping.remove("HashMap"); + this.importMapping.remove("Array"); + this.importMapping.remove("ArrayList"); + this.importMapping.remove("List"); + this.importMapping.remove("Set"); + this.importMapping.remove("DateTime"); + this.importMapping.remove("UUID"); + this.instantiationTypes.put("array", "java.util.ArrayList"); + this.instantiationTypes.put("map", "java.util.HashMap"); + } + // optional jackson mappings for BigDecimal support + this.importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); + this.importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); + + // imports for pojos + this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); + this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); + this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); + this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); + this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); + this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); + this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); + this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); + this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); + this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); + this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); + this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); + this.importMapping.put("IOException", "java.io.IOException"); + this.importMapping.put("Objects", "java.util.Objects"); + this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); + // import JsonCreator if JsonProperty is imported + // used later in recursive import in postProcessingModels + this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", + "com.fasterxml.jackson.annotation.JsonCreator"); + + this.apiTemplateFiles.put("api.mustache", ".java"); + this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); + + this.modelTemplateFiles.put("model.mustache", ".java"); + + this.supportingFiles.add(new SupportingFile("SpringBootApplication.mustache", + (this.getSourceFolder() + File.separator + this.getBasePackage()).replace(".", File.separator), + this.getServiceName() + "Application" + ".java")); + + this.supportingFiles + .add(new SupportingFile("config" + File.separator + "swaggerDocumentationConfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", + java.io.File.separator) + File.separator + "swagger", + "SwaggerDocumentationConfig.java")); + + this.supportingFiles.add(new SupportingFile("config" + File.separator + "pkmstproperties.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator + "swagger", + "PkmstProperties.java")); + this.supportingFiles.add(new SupportingFile("config" + File.separator + "appconfig.mustache", + (this.sourceFolder + File.separator + this.getConfigPackage()).replace(".", java.io.File.separator) + + File.separator, + "AppConfig.java")); + + // Security + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "authorizationServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "AuthorizationServerConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "oAuth2SecurityConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "OAuth2SecurityConfiguration.java")); + this.supportingFiles + .add(new SupportingFile("security" + File.separator + "resourceServerConfiguration.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "security", + "ResourceServerConfiguration.java")); + + // logging + + this.supportingFiles.add(new SupportingFile("logging" + File.separator + "httpLoggingFilter.mustache", + (this.sourceFolder + File.separator + this.basePackage).replace(".", File.separator) + File.separator + + "logging", + "HttpLoggingFilter.java")); + + // Resources + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-local.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-local.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "application-dev-config.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "application-dev-config.yml")); + this.supportingFiles.add(new SupportingFile("resources" + File.separator + "bootstrap.mustache", + ("src.main.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + + // POM + this.supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + + // Readme + this.supportingFiles.add(new SupportingFile("readme.mustache", "", "Readme.md")); + + // manifest + + this.supportingFiles.add(new SupportingFile("manifest.mustache", "", "manifest.yml")); + + // docker + this.supportingFiles.add(new SupportingFile("docker.mustache", "", "Dockerfile")); + + // logstash + + this.supportingFiles.add(new SupportingFile("logstash.mustache", "", "logstash.conf")); + + // Cucumber + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "executeReport.mustache", + this.testFolder + File.separator + this.basePackage.replace(".", File.separator) + File.separator + + "cucumber" + File.separator + "report", + "ExecuteReport.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberTest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Test.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "cucumberSteps.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "Steps.java")); + + this.supportingFiles.add(new SupportingFile( + "cucumber" + File.separator + "package.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "cucumber", + serviceName + "package-info.java")); + + // test resources + this.supportingFiles.add(new SupportingFile("cucumber" + File.separator + "cucumber.mustache", + (("src.test.resources") + File.separator + this.basePackage).replace(".", File.separator) + + File.separator + "cucumber", + serviceName + ".feature")); + + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "bootstrap.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "bootstrap.yml")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.properties")); + this.supportingFiles.add(new SupportingFile("testresources" + File.separator + "application-test.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application-test.properties")); + + // Gatling + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "gatling.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "gatling.conf")); + + this.supportingFiles.add(new SupportingFile("gatling" + File.separator + "application.mustache", + ("src.test.resources").replace(".", java.io.File.separator), "application.conf")); + + this.supportingFiles.add(new SupportingFile( + "gatling" + File.separator + "testapi.mustache", ("src") + File.separator + ("test") + File.separator + + ("scala") + File.separator + ("scalaFiles").replace(".", java.io.File.separator), + "testapi.scala")); + + /* + * this.supportingFiles.add(new SupportingFile( "gatling" + + * File.separator + "package.mustache", ("src")+ File.separator + + * ("test")+ File.separator + ("scala")+ File.separator + + * ("scalaFiles").replace(".", java.io.File.separator), + * "package.info")); + */ + + // adding class for integration test + this.supportingFiles.add(new SupportingFile( + "integration" + File.separator + "integrationtest.mustache", this.testFolder + File.separator + + this.basePackage.replace(".", File.separator) + File.separator + "controller", + serviceName + "IT.java")); + } + + @Override + public Map postProcessOperations(Map objs) { + Map operations = (Map) objs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (final CodegenOperation operation : ops) { + List responses = operation.responses; + if (responses != null) { + for (final CodegenResponse resp : responses) { + if ("0".equals(resp.code)) { + resp.code = "200"; + } + doDataTypeAssignment(resp.dataType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + resp.dataType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + resp.containerType = returnContainer; + } + }); + } + } + + doDataTypeAssignment(operation.returnType, new DataTypeAssigner() { + + public void setReturnType(final String returnType) { + operation.returnType = returnType; + } + + public void setReturnContainer(final String returnContainer) { + operation.returnContainer = returnContainer; + } + }); + + if (implicitHeaders) { + removeHeadersFromAllParams(operation.allParams); + } + } + } + + return objs; + } + + /** + * This method removes header parameters from the list of parameters and + * also corrects last allParams hasMore state. + * + * @param allParams + * list of all parameters + */ + private void removeHeadersFromAllParams(List allParams) { + if (allParams.isEmpty()) { + return; + } + final ArrayList copy = new ArrayList(allParams); + allParams.clear(); + + for (CodegenParameter p : copy) { + if (!p.isHeaderParam) { + allParams.add(p); + } + } + allParams.get(allParams.size() - 1).hasMore = false; + } + + /** + * @param returnType + * The return type that needs to be converted + * @param dataTypeAssigner + * An object that will assign the data to the respective fields + * in the model. + */ + private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAssigner) { + final String rt = returnType; + if (rt == null) { + dataTypeAssigner.setReturnType("Void"); + } else if (rt.startsWith("List")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("List<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("List"); + } + } else if (rt.startsWith("Map")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Map<".length(), end).split(",")[1].trim()); + dataTypeAssigner.setReturnContainer("Map"); + } + } else if (rt.startsWith("Set")) { + int end = rt.lastIndexOf(">"); + if (end > 0) { + dataTypeAssigner.setReturnType(rt.substring("Set<".length(), end).trim()); + dataTypeAssigner.setReturnContainer("Set"); + } + } + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + + swaggerType = getAlias(swaggerType); + + // don't apply renaming on types from the typeMapping + if (this.typeMapping.containsKey(swaggerType)) { + return this.typeMapping.get(swaggerType); + } + + if (null == swaggerType) { + LOGGER.error("No Type defined for Property " + p); + } + return toModelName(swaggerType); + } + + @Override + public String getAlias(String name) { + if (typeAliases.containsKey(name)) { + return typeAliases.get(name); + } + return name; + } + + @Override + public String toModelName(final String name) { + // We need to check if import-mapping has a different model for this + // class, so + // we use it + // instead of the auto-generated one. + if (this.importMapping.containsKey(name)) { + return this.importMapping.get(name); + } + + final String sanitizedName = sanitizeName(name); + + String nameWithPrefixSuffix = sanitizedName; + if (!StringUtils.isEmpty(modelNamePrefix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; + } + + if (!StringUtils.isEmpty(modelNameSuffix)) { + // add '_' so that model name can be camelized correctly + nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; + } + + // camelize the model name + // phone_number => PhoneNumber + final String camelizedName = camelize(nameWithPrefixSuffix); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(camelizedName)) { + final String modelName = "Model" + camelizedName; + LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); + return modelName; + } + + // model name starts with number + if (camelizedName.matches("^\\d.*")) { + final String modelName = "Model" + camelizedName; // e.g. + // 200Response + // => + // Model200Response + // (after + // camelize) + LOGGER.warn( + name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName); + return modelName; + } + + return camelizedName; + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + if (serializeBigDecimalAsString) { + if (property.baseType.equals("BigDecimal")) { + // we serialize BigDecimal as `string` to avoid precision loss + property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); + + // this requires some more imports to be added for this model... + model.imports.add("ToStringSerializer"); + model.imports.add("JsonSerialize"); + } + } + + if (!fullJavaUtil) { + if ("array".equals(property.containerType)) { + model.imports.add("ArrayList"); + } else if ("map".equals(property.containerType)) { + model.imports.add("HashMap"); + } + } + + if (!BooleanUtils.toBoolean(model.isEnum)) { + // needed by all pojos, but not enums + model.imports.add("ApiModelProperty"); + model.imports.add("ApiModel"); + } + + // super.postProcessModelProperty(model, property); + + if ("null".equals(property.example)) { + property.example = null; + } + + // Add imports for Jackson + if (!Boolean.TRUE.equals(model.isEnum)) { + model.imports.add("JsonProperty"); + + if (Boolean.TRUE.equals(model.hasEnums)) { + model.imports.add("JsonValue"); + } + } else { // enum class + // Needed imports for Jackson's JsonCreator + if (this.additionalProperties.containsKey("jackson")) { + model.imports.add("JsonCreator"); + } + } + } + + @Override + public Map postProcessModelsEnum(Map objs) { + objs = super.postProcessModelsEnum(objs); + + // Add imports for Jackson + List> imports = (List>) objs.get("imports"); + List models = (List) objs.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + // for enum model + if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { + cm.imports.add(this.importMapping.get("JsonValue")); + Map item = new HashMap(); + item.put("import", this.importMapping.get("JsonValue")); + imports.add(item); + } + } + + return objs; + } + + @Override + public CodegenModel fromModel(String name, Model model, Map allDefinitions) { + CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); + if (codegenModel.description != null) { + codegenModel.imports.add("ApiModel"); + } + if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { + codegenModel.imports.add("JsonSubTypes"); + codegenModel.imports.add("JsonTypeInfo"); + } + if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { + final Model parentModel = allDefinitions.get(codegenModel.parentSchema); + final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); + codegenModel = JavaPKMSTServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); + } + return codegenModel; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + return objs; + } + + @Override + public Map postProcessModels(Map objs) { + // recursively add import for mapping one type to multiple imports + List> recursiveImports = (List>) objs.get("imports"); + if (recursiveImports == null) { + return objs; + } + + ListIterator> listIterator = recursiveImports.listIterator(); + while (listIterator.hasNext()) { + String _import = listIterator.next().get("import"); + // if the import package happens to be found in the importMapping + // (key) + // add the corresponding import package to the list + if (importMapping.containsKey(_import)) { + Map newImportMap = new HashMap(); + newImportMap.put("import", importMapping.get(_import)); + listIterator.add(newImportMap); + } + } + + return postProcessModelsEnum(objs); + } + + @Override + public void preprocessSwagger(Swagger swagger) { + super.preprocessSwagger(swagger); + if (swagger == null || swagger.getPaths() == null) { + return; + } + if (swagger.getTags() != null) { + System.out.println("Tags are::" + swagger.getTags()); + List resourcePaths = new ArrayList(); + for (Tag tag : swagger.getTags()) { + ResourcePath resourcePath = new ResourcePath(); + resourcePath.setPath(tag.getName()); + resourcePaths.add(resourcePath); + } + this.additionalProperties.put("resourcePaths", resourcePaths); + } + // get vendor extensions + + Map vendorExt = swagger.getInfo().getVendorExtensions(); + if (vendorExt != null && !vendorExt.toString().equals("")) { + if (vendorExt.containsKey("x-codegen")) { + + Map uris = (Map) vendorExt.get("x-codegen"); + if (uris.containsKey("eurekaUri")) { + String eurekaUri = uris.get("eurekaUri"); + additionalProperties.put(EUREKA_URI, eurekaUri); + } + if (uris.containsKey("zipkinUri")) { + String zipkinUri = uris.get("zipkinUri"); + additionalProperties.put(ZIPKIN_URI, zipkinUri); + } + if (uris.containsKey("springBootAdminUri")) { + String springBootAdminUri = uris.get("springBootAdminUri"); + additionalProperties.put(SPRINGADMIN_URI, springBootAdminUri); + } + if (uris.containsKey("pkmstInterceptor")) { + String pkmstInterceptor = uris.get("pkmstInterceptor"); + additionalProperties.put("pkmstInterceptor", pkmstInterceptor); + } + } + } + + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() == null) { + continue; + } + for (Operation operation : path.getOperations()) { + boolean hasFormParameters = false; + for (Parameter parameter : operation.getParameters()) { + if (parameter instanceof FormParameter) { + hasFormParameters = true; + } + } + // only add content-Type if its no a GET-Method + if (path.getGet() != null || !operation.equals(path.getGet())) { + String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" + : "application/json"; + String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() + ? defaultContentType : operation.getConsumes().get(0); + operation.setVendorExtension("x-contentType", contentType); + } + String accepts = getAccept(operation); + operation.setVendorExtension("x-accepts", accepts); + } + } + + if ("/".equals(swagger.getBasePath())) { + swagger.setBasePath(""); + } + + if (!additionalProperties.containsKey(TITLE)) { + // From the title, compute a reasonable name for the package and the + // API + String title = swagger.getInfo().getTitle(); + + // Drop any API suffix + if (title != null) { + title = title.trim().replace(" ", "-"); + if (title.toUpperCase().endsWith("API")) { + title = title.substring(0, title.length() - 3); + } + + this.title = camelize(sanitizeName(title), true); + } + additionalProperties.put(TITLE, this.title); + } + + String host = swagger.getHost(); + String port = "8008"; + if (host != null) { + String[] parts = host.split(":"); + if (parts.length > 1) { + port = parts[1]; + } + } + + this.additionalProperties.put("serverPort", port); + if (swagger.getPaths() != null) { + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() != null) { + for (Operation operation : path.getOperations()) { + if (operation.getTags() != null) { + List> tags = new ArrayList>(); + for (String tag : operation.getTags()) { + Map value = new HashMap(); + value.put("tag", tag); + value.put("hasMore", "true"); + tags.add(value); + } + if (tags.size() > 0) { + tags.get(tags.size() - 1).remove("hasMore"); + } + if (operation.getTags().size() > 0) { + String tag = operation.getTags().get(0); + operation.setTags(Arrays.asList(tag)); + } + operation.setVendorExtension("x-tags", tags); + } + } + } + } + } + } + + @Override + public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, + Map> operations) { + String basePath = resourcePath; + if (basePath.startsWith("/")) { + basePath = basePath.substring(1); + } + int pos = basePath.indexOf("/"); + if (pos > 0) { + basePath = basePath.substring(0, pos); + } + + if (basePath.equals("")) { + basePath = "default"; + } else { + co.subresourceOperation = !co.path.isEmpty(); + } + List opList = operations.get(basePath); + if (opList == null) { + opList = new ArrayList(); + operations.put(basePath, opList); + } + opList.add(co); + co.baseName = basePath; + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultApi"; + } + name = sanitizeName(name); + return camelize(name) + "Api"; + } + + @Override + public void setParameterExampleValue(CodegenParameter p) { + String type = p.baseType; + if (type == null) { + type = p.dataType; + } + + if ("File".equals(type)) { + String example; + + if (p.defaultValue == null) { + example = p.example; + } else { + example = p.defaultValue; + } + + if (example == null) { + example = "/path/to/file"; + } + example = "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText(example) + + "\"))"; + p.example = example; + } else { + super.setParameterExampleValue(p); + } + } + + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; + } + + @Override + public String apiFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String apiTestFileFolder() { + return this.outputFolder + "/" + this.testFolder + "/" + apiPackage().replace(".", "/"); + } + + @Override + public String modelFileFolder() { + return this.outputFolder + "/" + this.sourceFolder + "/" + modelPackage().replace(".", "/"); + } + + @Override + public String apiDocFileFolder() { + return (this.outputFolder + "/" + this.apiDocPath).replace("/", File.separator); + } + + @Override + public String modelDocFileFolder() { + return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName(name); // FIXME: a parameter should not be assigned. + // Also declare the methods + // parameters as 'final'. + + if (name.toLowerCase().matches("^_*class$")) { + return "propertyClass"; + } + + if ("_".equals(name)) { + name = "_u"; + } + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + if (startsWithTwoUppercaseLetters(name)) { + name = name.substring(0, 2).toLowerCase() + name.substring(2); + } + + // camelize (lower first character) the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved word or word starting with number, append _ + if (isReservedWord(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public String toParamName(String name) { + // to avoid conflicts with 'callback' parameter for async call + if ("callback".equals(name)) { + return "paramCallback"; + } + + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + if (inner == null) { + LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning + // null + return null; + } + return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + if (inner == null) { + LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); + // TODO maybe better defaulting to StringProperty than returning + // null + return null; + } + return getSwaggerType(p) + ""; + } + return super.getTypeDeclaration(p); + } + + @Override + public String toDefaultValue(Property p) { + if (p instanceof ArrayProperty) { + final ArrayProperty ap = (ArrayProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.ArrayList<%s>()"; + } else { + pattern = "new ArrayList<%s>()"; + } + if (ap.getItems() == null) { + return null; + } + + return String.format(pattern, getTypeDeclaration(ap.getItems())); + } else if (p instanceof MapProperty) { + final MapProperty ap = (MapProperty) p; + final String pattern; + if (fullJavaUtil) { + pattern = "new java.util.HashMap<%s>()"; + } else { + pattern = "new HashMap<%s>()"; + } + if (ap.getAdditionalProperties() == null) { + return null; + } + + return String.format(pattern, + String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); + } else if (p instanceof IntegerProperty) { + IntegerProperty dp = (IntegerProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + return "null"; + } else if (p instanceof LongProperty) { + LongProperty dp = (LongProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "l"; + } + return "null"; + } else if (p instanceof DoubleProperty) { + DoubleProperty dp = (DoubleProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "d"; + } + return "null"; + } else if (p instanceof FloatProperty) { + FloatProperty dp = (FloatProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString() + "f"; + } + return "null"; + } else if (p instanceof BooleanProperty) { + BooleanProperty bp = (BooleanProperty) p; + if (bp.getDefault() != null) { + return bp.getDefault().toString(); + } + return "null"; + } else if (p instanceof StringProperty) { + StringProperty sp = (StringProperty) p; + if (sp.getDefault() != null) { + String _default = sp.getDefault(); + if (sp.getEnum() == null) { + return "\"" + escapeText(_default) + "\""; + } else { + // convert to enum var name later in postProcessModels + return _default; + } + } + return "null"; + } + return super.toDefaultValue(p); + } + + @Override + public String toExampleValue(Property p) { + if (p.getExample() != null) { + return escapeText(p.getExample().toString()); + } else { + return super.toExampleValue(p); + } + } + + @Override + public String toOperationId(String operationId) { + // throw exception if method name is empty + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method/operation name (operationId) not allowed"); + } + + operationId = camelize(sanitizeName(operationId), true); + + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + String newOperationId = camelize("call_" + operationId, true); + LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); + return newOperationId; + } + + return operationId; + } + + @Override + protected boolean needToImport(String type) { + return super.needToImport(type) && type.indexOf(".") < 0; + } + + @Override + public String toEnumName(CodegenProperty property) { + return sanitizeName(camelize(property.name)) + "Enum"; + } + + @Override + public String toEnumVarName(String value, String datatype) { + if (value.length() == 0) { + return "EMPTY"; + } + + // for symbol, e.g. $, # + if (getSymbolName(value) != null) { + return getSymbolName(value).toUpperCase(); + } + + // number + if ("Integer".equals(datatype) || "Long".equals(datatype) || "Float".equals(datatype) + || "Double".equals(datatype)) { + String varName = "NUMBER_" + value; + varName = varName.replace("-", "MINUS_"); + varName = varName.replace("\\+", "PLUS_"); + varName = varName.replace("\\.", "_DOT_"); + return varName; + } + + // string + String var = value.replace("\\W+", "_").toUpperCase(); + if (var.matches("\\d.*")) { + return "_" + var; + } else { + return var; + } + } + + @Override + public String toEnumValue(String value, String datatype) { + if ("Integer".equals(datatype) || "Long".equals(datatype) || "Double".equals(datatype)) { + return value; + } else if ("Float".equals(datatype)) { + // add f to number, e.g. 3.14 => 3.14f + return value + "f"; + } else { + return "\"" + escapeText(value) + "\""; + } + } + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, + Map definitions, Swagger swagger) { + CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); + op.path = sanitizePath(op.path); + return op; + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + public boolean convertPropertyToBoolean(String propertyKey) { + boolean booleanValue = false; + if (additionalProperties.containsKey(propertyKey)) { + booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); + } + + return booleanValue; + } + + public String toRegularExpression(String pattern) { + return escapeText(pattern); + } + + @Override + public String sanitizeTag(String tag) { + return camelize(sanitizeName(tag)); + } + + public String toBooleanGetter(String name) { + return "is" + getterAndSetterCapitalize(name); + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getArtifactVersion() { + return artifactVersion; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public String getProjectFolder() { + return projectFolder; + } + + public void setProjectFolder(String projectFolder) { + this.projectFolder = projectFolder; + } + + public String getEurekaUri() { + return eurekaUri; + } + + public void setEurekaUri(String eurekaUri) { + this.eurekaUri = eurekaUri; + } + + public String getZipkinUri() { + return zipkinUri; + } + + public void setZipkinUri(String zipkinUri) { + this.zipkinUri = zipkinUri; + } + + public String getSpringBootAdminUri() { + return springBootAdminUri; + } + + public void setSpringBootAdminUri(String springBootAdminUri) { + this.springBootAdminUri = springBootAdminUri; + } + + public String getProjectTestFolder() { + return projectTestFolder; + } + + public void setProjectTestFolder(String projectTestFolder) { + this.projectTestFolder = projectTestFolder; + } + + public String getSourceFolder() { + return sourceFolder; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } + + public String getTestFolder() { + return testFolder; + } + + public void setTestFolder(String testFolder) { + this.testFolder = testFolder; + } - public String getBasePackage() { - return basePackage; - } + public String getBasePackage() { + return basePackage; + } - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - } + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } - public String getServiceName() { - return serviceName; - } + public String getServiceName() { + return serviceName; + } - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } - public String getConfigPackage() { - return configPackage; - } + public String getConfigPackage() { + return configPackage; + } - public void setConfigPackage(String configPackage) { - this.configPackage = configPackage; - } + public void setConfigPackage(String configPackage) { + this.configPackage = configPackage; + } - public boolean isImplicitHeaders() { - return implicitHeaders; - } + public boolean isImplicitHeaders() { + return implicitHeaders; + } - public void setImplicitHeaders(boolean implicitHeaders) { - this.implicitHeaders = implicitHeaders; - } + public void setImplicitHeaders(boolean implicitHeaders) { + this.implicitHeaders = implicitHeaders; + } - public boolean isSerializeBigDecimalAsString() { - return serializeBigDecimalAsString; - } + public boolean isSerializeBigDecimalAsString() { + return serializeBigDecimalAsString; + } - public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { - this.serializeBigDecimalAsString = serializeBigDecimalAsString; - } + public void setSerializeBigDecimalAsString(boolean serializeBigDecimalAsString) { + this.serializeBigDecimalAsString = serializeBigDecimalAsString; + } - public boolean isFullJavaUtil() { - return fullJavaUtil; - } + public boolean isFullJavaUtil() { + return fullJavaUtil; + } - public void setFullJavaUtil(boolean fullJavaUtil) { - this.fullJavaUtil = fullJavaUtil; - } + public void setFullJavaUtil(boolean fullJavaUtil) { + this.fullJavaUtil = fullJavaUtil; + } - public Boolean getSerializableModel() { - return serializableModel; - } + public Boolean getSerializableModel() { + return serializableModel; + } - public void setSerializableModel(Boolean serializableModel) { - this.serializableModel = serializableModel; - } + public void setSerializableModel(Boolean serializableModel) { + this.serializableModel = serializableModel; + } - public String getInvokerPackage() { - return invokerPackage; - } + public String getInvokerPackage() { + return invokerPackage; + } - public void setInvokerPackage(String invokerPackage) { - this.invokerPackage = invokerPackage; - } + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } - public String getTitle() { - return title; - } + public String getTitle() { + return title; + } - public void setTitle(String title) { - this.title = title; - } + public void setTitle(String title) { + this.title = title; + } - public boolean isWithXml() { - return withXml; - } + public boolean isWithXml() { + return withXml; + } - public void setWithXml(boolean withXml) { - this.withXml = withXml; - } + public void setWithXml(boolean withXml) { + this.withXml = withXml; + } - private boolean startsWithTwoUppercaseLetters(String name) { - boolean startsWithTwoUppercaseLetters = false; - if (name.length() > 1) { - startsWithTwoUppercaseLetters = name.substring(0, 2).equals(name.substring(0, 2).toUpperCase()); - } - return startsWithTwoUppercaseLetters; - } + private boolean startsWithTwoUppercaseLetters(String name) { + boolean startsWithTwoUppercaseLetters = false; + if (name.length() > 1) { + startsWithTwoUppercaseLetters = name.substring(0, 2).equals(name.substring(0, 2).toUpperCase()); + } + return startsWithTwoUppercaseLetters; + } - private String sanitizePath(String p) { - // prefer replace a ", instead of a fuLL URL encode for readability - return p.replace("\"", "%22"); - } + private String sanitizePath(String p) { + // prefer replace a ", instead of a fuLL URL encode for readability + return p.replace("\"", "%22"); + } - private interface DataTypeAssigner { + private interface DataTypeAssigner { - void setReturnType(String returnType); + void setReturnType(String returnType); - void setReturnContainer(String returnContainer); - } + void setReturnContainer(String returnContainer); + } - private class ResourcePath { + private class ResourcePath { - private String path; + private String path; - public String getPath() { - return path; - } + public String getPath() { + return path; + } - public void setPath(String path) { - this.path = path; - } + public void setPath(String path) { + this.path = path; + } - @Override - public String toString() { - return this.path; - } - } + @Override + public String toString() { + return this.path; + } + } } From dc941aac606d10a5270d3d53dcddeb1ea7c09232 Mon Sep 17 00:00:00 2001 From: sanshuman Date: Fri, 8 Dec 2017 20:43:25 +0530 Subject: [PATCH 12/19] updated codegen which extends abstractjavacodegen --- .../languages/JavaPKMSTServerCodegen.java | 672 +----------------- .../resources/pkmst/apiException.mustache | 10 - .../resources/pkmst/apiOriginFilter.mustache | 27 - .../pkmst/apiResponseMessage.mustache | 69 -- .../src/main/resources/pkmst/api_doc.mustache | 82 --- .../main/resources/pkmst/model_doc.mustache | 3 - .../main/resources/pkmst/pojo_doc.mustache | 15 - .../src/main/resources/pkmst/pom.mustache | 5 + 8 files changed, 21 insertions(+), 862 deletions(-) delete mode 100644 modules/swagger-codegen/src/main/resources/pkmst/apiException.mustache delete mode 100644 modules/swagger-codegen/src/main/resources/pkmst/apiOriginFilter.mustache delete mode 100644 modules/swagger-codegen/src/main/resources/pkmst/apiResponseMessage.mustache delete mode 100644 modules/swagger-codegen/src/main/resources/pkmst/api_doc.mustache delete mode 100644 modules/swagger-codegen/src/main/resources/pkmst/model_doc.mustache delete mode 100644 modules/swagger-codegen/src/main/resources/pkmst/pojo_doc.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java index 174467a8ef1..bba08e23529 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java @@ -4,17 +4,10 @@ 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.ListIterator; import java.util.Map; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; - import io.swagger.codegen.CliOption; -import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenModel; import io.swagger.codegen.CodegenOperation; @@ -22,29 +15,18 @@ import io.swagger.codegen.CodegenProperty; import io.swagger.codegen.CodegenResponse; import io.swagger.codegen.CodegenType; -import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.SupportingFile; -import io.swagger.models.Model; import io.swagger.models.Operation; import io.swagger.models.Path; import io.swagger.models.Swagger; import io.swagger.models.Tag; import io.swagger.models.parameters.FormParameter; import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.ArrayProperty; -import io.swagger.models.properties.BooleanProperty; -import io.swagger.models.properties.DoubleProperty; -import io.swagger.models.properties.FloatProperty; -import io.swagger.models.properties.IntegerProperty; -import io.swagger.models.properties.LongProperty; -import io.swagger.models.properties.MapProperty; -import io.swagger.models.properties.Property; -import io.swagger.models.properties.StringProperty; /** * Created by prokarma on 04/09/17. */ -public class JavaPKMSTServerCodegen extends DefaultCodegen implements CodegenConfig { +public class JavaPKMSTServerCodegen extends AbstractJavaCodegen { public static final String FULL_JAVA_UTIL = "fullJavaUtil"; public static final String SUPPORT_JAVA6 = "supportJava6"; @@ -55,11 +37,7 @@ public class JavaPKMSTServerCodegen extends DefaultCodegen implements CodegenCon public static final String EUREKA_URI = "eurekaUri"; public static final String ZIPKIN_URI = "zipkinUri"; public static final String SPRINGADMIN_URI = "springBootAdminUri"; - protected String groupId = "com.prokarma"; - protected String artifactId = "pkmst-microservice"; - protected String artifactVersion = "1.0.0"; protected String projectFolder; - protected String projectTestFolder; protected String sourceFolder; protected String testFolder; @@ -74,8 +52,6 @@ public class JavaPKMSTServerCodegen extends DefaultCodegen implements CodegenCon protected Boolean serializableModel = false; protected String invokerPackage; protected String title; - protected String apiDocPath = "docs/"; - protected String modelDocPath = "docs/"; protected String eurekaUri; protected String zipkinUri; protected String springBootAdminUri; @@ -86,31 +62,13 @@ public JavaPKMSTServerCodegen() { this.projectTestFolder = "src" + File.separator + "test"; this.sourceFolder = this.projectFolder + File.separator + "java"; this.testFolder = this.projectTestFolder + File.separator + "java"; + groupId = "com.prokarma"; + artifactId = "pkmst-microservice"; + artifactVersion = "1.0.0"; embeddedTemplateDir = templateDir = "pkmst"; apiPackage = "com.prokarma.pkmst.controller"; modelPackage = "com.prokarma.pkmst.model"; invokerPackage = "com.prokarma.pkmst.controller"; - setReservedWordsLowerCase(Arrays.asList( - // used as internal variables, can collide with parameter names - "localVarPath", "localVarQueryParams", "localVarCollectionQueryParams", "localVarHeaderParams", - "localVarFormParams", "localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes", - "localVarContentType", "localVarAuthNames", "localReturnType", "ApiClient", "ApiException", - "ApiResponse", "Configuration", "StringUtil", - - // language reserved words - "abstract", "continue", "for", "new", "switch", "assert", "default", "if", "package", "synchronized", - "boolean", "do", "goto", "private", "this", "break", "double", "implements", "protected", "throw", - "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", - "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", - "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while", "null")); - - this.languageSpecificPrimitives = new HashSet(Arrays.asList("String", "boolean", "Boolean", "Double", - "Integer", "Long", "Float", "Object", "byte[]")); - this.instantiationTypes.put("array", "ArrayList"); - this.instantiationTypes.put("map", "HashMap"); - this.typeMapping.put("date", "Date"); - this.typeMapping.put("file", "File"); - this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); @@ -123,61 +81,8 @@ public JavaPKMSTServerCodegen() { // Middleware config this.cliOptions.add(new CliOption("pkmstInterceptor", "PKMST Interceptor")); this.apiTestTemplateFiles.put("api_test.mustache", ".java"); - this.modelDocTemplateFiles.put("model_doc.mustache", ".md"); - this.apiDocTemplateFiles.put("api_doc.mustache", ".md"); - } - - private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { - // This generator uses inline classes to define enums, which breaks when - // dealing with models that have subTypes. To clean this up, we will - // analyze - // the parent and child models, look for enums that match, and remove - // them from the child models and leave them in the parent. - // Because the child models extend the parents, the enums will be - // available via - // the parent. - - // Only bother with reconciliation if the parent model has enums. - if (!parentCodegenModel.hasEnums) { - return codegenModel; - } - - // Get the properties for the parent and child models - final List parentModelCodegenProperties = parentCodegenModel.vars; - List codegenProperties = codegenModel.vars; - - // Iterate over all of the parent model properties - boolean removedChildEnum = false; - for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) { - // Look for enums - if (parentModelCodegenPropery.isEnum) { - // Now that we have found an enum in the parent class, - // and search the child class for the same enum. - Iterator iterator = codegenProperties.iterator(); - while (iterator.hasNext()) { - CodegenProperty codegenProperty = iterator.next(); - if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) { - // We found an enum in the child class that is - // a duplicate of the one in the parent, so remove it. - iterator.remove(); - removedChildEnum = true; - } - } - } - } - - if (removedChildEnum) { - // If we removed an entry from this model's vars, we need to ensure - // hasMore is - // updated - int count = 0, numVars = codegenProperties.size(); - for (CodegenProperty codegenProperty : codegenProperties) { - count += 1; - codegenProperty.hasMore = (count < numVars) ? true : false; - } - codegenModel.vars = codegenProperties; - } - return codegenModel; + this.modelDocTemplateFiles.remove("model_doc.mustache", ".md"); + this.apiDocTemplateFiles.remove("api_doc.mustache", ".md"); } private static String getAccept(Operation operation) { @@ -215,7 +120,7 @@ public String getName() { } public String getHelp() { - return "Generates a Java SpringBoot Server application using the SpringFox integration." + return "Generates a PKMST SpringBoot Server application using the SpringFox integration." + " Also enables EurekaServerClient / Zipkin / Spring-Boot admin"; } @@ -227,9 +132,6 @@ public void processOpts() { this.apiPackage = this.getBasePackage() + ".controller"; this.modelPackage = this.getBasePackage() + ".model"; this.setConfigPackage(this.getBasePackage() + ".config"); - - // this.additionalProperties.put(BASE_PACKAGE, - // this.getBasePackage()); } else { this.additionalProperties.put(BASE_PACKAGE, basePackage); this.additionalProperties.put(CONFIG_PACKAGE, this.getConfigPackage()); @@ -300,55 +202,6 @@ public void processOpts() { } this.additionalProperties.put(WITH_XML, withXml); - // make api and model doc path available in mustache template - this.additionalProperties.put("apiDocPath", apiDocPath); - this.additionalProperties.put("modelDocPath", modelDocPath); - - this.importMapping.put("List", "java.util.List"); - - if (fullJavaUtil) { - this.typeMapping.put("array", "java.util.List"); - this.typeMapping.put("map", "java.util.Map"); - this.typeMapping.put("DateTime", "java.util.Date"); - this.typeMapping.put("UUID", "java.util.UUID"); - this.typeMapping.remove("List"); - this.importMapping.remove("Date"); - this.importMapping.remove("Map"); - this.importMapping.remove("HashMap"); - this.importMapping.remove("Array"); - this.importMapping.remove("ArrayList"); - this.importMapping.remove("List"); - this.importMapping.remove("Set"); - this.importMapping.remove("DateTime"); - this.importMapping.remove("UUID"); - this.instantiationTypes.put("array", "java.util.ArrayList"); - this.instantiationTypes.put("map", "java.util.HashMap"); - } - // optional jackson mappings for BigDecimal support - this.importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); - this.importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); - - // imports for pojos - this.importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); - this.importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); - this.importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); - this.importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); - this.importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); - this.importMapping.put("JsonCreator", "com.fasterxml.jackson.annotation.JsonCreator"); - this.importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); - this.importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName"); - this.importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter"); - this.importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter"); - this.importMapping.put("JsonReader", "com.google.gson.stream.JsonReader"); - this.importMapping.put("JsonWriter", "com.google.gson.stream.JsonWriter"); - this.importMapping.put("IOException", "java.io.IOException"); - this.importMapping.put("Objects", "java.util.Objects"); - this.importMapping.put("StringUtil", getInvokerPackage() + ".StringUtil"); - // import JsonCreator if JsonProperty is imported - // used later in recursive import in postProcessingModels - this.importMapping.put("com.fasterxml.jackson.annotation.JsonProperty", - "com.fasterxml.jackson.annotation.JsonCreator"); - this.apiTemplateFiles.put("api.mustache", ".java"); this.apiTemplateFiles.put("apiController.mustache", "Controller.java"); @@ -470,14 +323,6 @@ public void processOpts() { + ("scala") + File.separator + ("scalaFiles").replace(".", java.io.File.separator), "testapi.scala")); - /* - * this.supportingFiles.add(new SupportingFile( "gatling" + - * File.separator + "package.mustache", ("src")+ File.separator + - * ("test")+ File.separator + ("scala")+ File.separator + - * ("scalaFiles").replace(".", java.io.File.separator), - * "package.info")); - */ - // adding class for integration test this.supportingFiles.add(new SupportingFile( "integration" + File.separator + "integrationtest.mustache", this.testFolder + File.separator @@ -485,6 +330,7 @@ public void processOpts() { serviceName + "IT.java")); } + @SuppressWarnings("unchecked") @Override public Map postProcessOperations(Map objs) { Map operations = (Map) objs.get("operations"); @@ -541,7 +387,7 @@ private void removeHeadersFromAllParams(List allParams) { if (allParams.isEmpty()) { return; } - final ArrayList copy = new ArrayList(allParams); + final ArrayList copy = new ArrayList<>(allParams); allParams.clear(); for (CodegenParameter p : copy) { @@ -584,109 +430,9 @@ private void doDataTypeAssignment(String returnType, DataTypeAssigner dataTypeAs } } - @Override - public String getSwaggerType(Property p) { - String swaggerType = super.getSwaggerType(p); - - swaggerType = getAlias(swaggerType); - - // don't apply renaming on types from the typeMapping - if (this.typeMapping.containsKey(swaggerType)) { - return this.typeMapping.get(swaggerType); - } - - if (null == swaggerType) { - LOGGER.error("No Type defined for Property " + p); - } - return toModelName(swaggerType); - } - - @Override - public String getAlias(String name) { - if (typeAliases.containsKey(name)) { - return typeAliases.get(name); - } - return name; - } - - @Override - public String toModelName(final String name) { - // We need to check if import-mapping has a different model for this - // class, so - // we use it - // instead of the auto-generated one. - if (this.importMapping.containsKey(name)) { - return this.importMapping.get(name); - } - - final String sanitizedName = sanitizeName(name); - - String nameWithPrefixSuffix = sanitizedName; - if (!StringUtils.isEmpty(modelNamePrefix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix; - } - - if (!StringUtils.isEmpty(modelNameSuffix)) { - // add '_' so that model name can be camelized correctly - nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix; - } - - // camelize the model name - // phone_number => PhoneNumber - final String camelizedName = camelize(nameWithPrefixSuffix); - - // model name cannot use reserved keyword, e.g. return - if (isReservedWord(camelizedName)) { - final String modelName = "Model" + camelizedName; - LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName); - return modelName; - } - - // model name starts with number - if (camelizedName.matches("^\\d.*")) { - final String modelName = "Model" + camelizedName; // e.g. - // 200Response - // => - // Model200Response - // (after - // camelize) - LOGGER.warn( - name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName); - return modelName; - } - - return camelizedName; - } - @Override public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - if (serializeBigDecimalAsString) { - if (property.baseType.equals("BigDecimal")) { - // we serialize BigDecimal as `string` to avoid precision loss - property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)"); - - // this requires some more imports to be added for this model... - model.imports.add("ToStringSerializer"); - model.imports.add("JsonSerialize"); - } - } - - if (!fullJavaUtil) { - if ("array".equals(property.containerType)) { - model.imports.add("ArrayList"); - } else if ("map".equals(property.containerType)) { - model.imports.add("HashMap"); - } - } - - if (!BooleanUtils.toBoolean(model.isEnum)) { - // needed by all pojos, but not enums - model.imports.add("ApiModelProperty"); - model.imports.add("ApiModel"); - } - - // super.postProcessModelProperty(model, property); + super.postProcessModelProperty(model, property); if ("null".equals(property.example)) { property.example = null; @@ -705,8 +451,10 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert model.imports.add("JsonCreator"); } } + } + @SuppressWarnings("unchecked") @Override public Map postProcessModelsEnum(Map objs) { objs = super.postProcessModelsEnum(objs); @@ -729,53 +477,7 @@ public Map postProcessModelsEnum(Map objs) { return objs; } - @Override - public CodegenModel fromModel(String name, Model model, Map allDefinitions) { - CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); - if (codegenModel.description != null) { - codegenModel.imports.add("ApiModel"); - } - if (codegenModel.discriminator != null && this.additionalProperties.containsKey("jackson")) { - codegenModel.imports.add("JsonSubTypes"); - codegenModel.imports.add("JsonTypeInfo"); - } - if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { - final Model parentModel = allDefinitions.get(codegenModel.parentSchema); - final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); - codegenModel = JavaPKMSTServerCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); - } - return codegenModel; - } - - @Override - public Map postProcessSupportingFileData(Map objs) { - return objs; - } - - @Override - public Map postProcessModels(Map objs) { - // recursively add import for mapping one type to multiple imports - List> recursiveImports = (List>) objs.get("imports"); - if (recursiveImports == null) { - return objs; - } - - ListIterator> listIterator = recursiveImports.listIterator(); - while (listIterator.hasNext()) { - String _import = listIterator.next().get("import"); - // if the import package happens to be found in the importMapping - // (key) - // add the corresponding import package to the list - if (importMapping.containsKey(_import)) { - Map newImportMap = new HashMap(); - newImportMap.put("import", importMapping.get(_import)); - listIterator.add(newImportMap); - } - } - - return postProcessModelsEnum(objs); - } - + @SuppressWarnings("unchecked") @Override public void preprocessSwagger(Swagger swagger) { super.preprocessSwagger(swagger); @@ -784,7 +486,7 @@ public void preprocessSwagger(Swagger swagger) { } if (swagger.getTags() != null) { System.out.println("Tags are::" + swagger.getTags()); - List resourcePaths = new ArrayList(); + List resourcePaths = new ArrayList<>(); for (Tag tag : swagger.getTags()) { ResourcePath resourcePath = new ResourcePath(); resourcePath.setPath(tag.getName()); @@ -905,27 +607,8 @@ public void preprocessSwagger(Swagger swagger) { @Override public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map> operations) { - String basePath = resourcePath; - if (basePath.startsWith("/")) { - basePath = basePath.substring(1); - } - int pos = basePath.indexOf("/"); - if (pos > 0) { - basePath = basePath.substring(0, pos); - } - - if (basePath.equals("")) { - basePath = "default"; - } else { - co.subresourceOperation = !co.path.isEmpty(); - } - List opList = operations.get(basePath); - if (opList == null) { - opList = new ArrayList(); - operations.put(basePath, opList); - } - opList.add(co); - co.baseName = basePath; + super.addOperationToGroup(tag, resourcePath, operation, co, operations); + co.subresourceOperation = !co.path.isEmpty(); } @Override @@ -937,41 +620,6 @@ public String toApiName(String name) { return camelize(name) + "Api"; } - @Override - public void setParameterExampleValue(CodegenParameter p) { - String type = p.baseType; - if (type == null) { - type = p.dataType; - } - - if ("File".equals(type)) { - String example; - - if (p.defaultValue == null) { - example = p.example; - } else { - example = p.defaultValue; - } - - if (example == null) { - example = "/path/to/file"; - } - example = "new org.springframework.core.io.FileSystemResource(new java.io.File(\"" + escapeText(example) - + "\"))"; - p.example = example; - } else { - super.setParameterExampleValue(p); - } - } - - @Override - public String escapeReservedWord(String name) { - if (this.reservedWordsMappings().containsKey(name)) { - return this.reservedWordsMappings().get(name); - } - return "_" + name; - } - @Override public String apiFileFolder() { return this.outputFolder + "/" + this.sourceFolder + "/" + apiPackage().replace(".", "/"); @@ -997,281 +645,6 @@ public String modelDocFileFolder() { return (this.outputFolder + "/" + this.modelDocPath).replace("/", File.separator); } - @Override - public String toVarName(String name) { - // sanitize name - name = sanitizeName(name); // FIXME: a parameter should not be assigned. - // Also declare the methods - // parameters as 'final'. - - if (name.toLowerCase().matches("^_*class$")) { - return "propertyClass"; - } - - if ("_".equals(name)) { - name = "_u"; - } - - // if it's all uppper case, do nothing - if (name.matches("^[A-Z_]*$")) { - return name; - } - - if (startsWithTwoUppercaseLetters(name)) { - name = name.substring(0, 2).toLowerCase() + name.substring(2); - } - - // camelize (lower first character) the variable name - // pet_id => petId - name = camelize(name, true); - - // for reserved word or word starting with number, append _ - if (isReservedWord(name) || name.matches("^\\d.*")) { - name = escapeReservedWord(name); - } - - return name; - } - - @Override - public String toParamName(String name) { - // to avoid conflicts with 'callback' parameter for async call - if ("callback".equals(name)) { - return "paramCallback"; - } - - // should be the same as variable name - return toVarName(name); - } - - @Override - public String toModelFilename(String name) { - // should be the same as the model name - return toModelName(name); - } - - @Override - public String getTypeDeclaration(Property p) { - if (p instanceof ArrayProperty) { - ArrayProperty ap = (ArrayProperty) p; - Property inner = ap.getItems(); - if (inner == null) { - LOGGER.warn(ap.getName() + "(array property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning - // null - return null; - } - return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; - } else if (p instanceof MapProperty) { - MapProperty mp = (MapProperty) p; - Property inner = mp.getAdditionalProperties(); - if (inner == null) { - LOGGER.warn(mp.getName() + "(map property) does not have a proper inner type defined"); - // TODO maybe better defaulting to StringProperty than returning - // null - return null; - } - return getSwaggerType(p) + ""; - } - return super.getTypeDeclaration(p); - } - - @Override - public String toDefaultValue(Property p) { - if (p instanceof ArrayProperty) { - final ArrayProperty ap = (ArrayProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.ArrayList<%s>()"; - } else { - pattern = "new ArrayList<%s>()"; - } - if (ap.getItems() == null) { - return null; - } - - return String.format(pattern, getTypeDeclaration(ap.getItems())); - } else if (p instanceof MapProperty) { - final MapProperty ap = (MapProperty) p; - final String pattern; - if (fullJavaUtil) { - pattern = "new java.util.HashMap<%s>()"; - } else { - pattern = "new HashMap<%s>()"; - } - if (ap.getAdditionalProperties() == null) { - return null; - } - - return String.format(pattern, - String.format("String, %s", getTypeDeclaration(ap.getAdditionalProperties()))); - } else if (p instanceof IntegerProperty) { - IntegerProperty dp = (IntegerProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - return "null"; - } else if (p instanceof LongProperty) { - LongProperty dp = (LongProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "l"; - } - return "null"; - } else if (p instanceof DoubleProperty) { - DoubleProperty dp = (DoubleProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "d"; - } - return "null"; - } else if (p instanceof FloatProperty) { - FloatProperty dp = (FloatProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString() + "f"; - } - return "null"; - } else if (p instanceof BooleanProperty) { - BooleanProperty bp = (BooleanProperty) p; - if (bp.getDefault() != null) { - return bp.getDefault().toString(); - } - return "null"; - } else if (p instanceof StringProperty) { - StringProperty sp = (StringProperty) p; - if (sp.getDefault() != null) { - String _default = sp.getDefault(); - if (sp.getEnum() == null) { - return "\"" + escapeText(_default) + "\""; - } else { - // convert to enum var name later in postProcessModels - return _default; - } - } - return "null"; - } - return super.toDefaultValue(p); - } - - @Override - public String toExampleValue(Property p) { - if (p.getExample() != null) { - return escapeText(p.getExample().toString()); - } else { - return super.toExampleValue(p); - } - } - - @Override - public String toOperationId(String operationId) { - // throw exception if method name is empty - if (StringUtils.isEmpty(operationId)) { - throw new RuntimeException("Empty method/operation name (operationId) not allowed"); - } - - operationId = camelize(sanitizeName(operationId), true); - - // method name cannot use reserved keyword, e.g. return - if (isReservedWord(operationId)) { - String newOperationId = camelize("call_" + operationId, true); - LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId); - return newOperationId; - } - - return operationId; - } - - @Override - protected boolean needToImport(String type) { - return super.needToImport(type) && type.indexOf(".") < 0; - } - - @Override - public String toEnumName(CodegenProperty property) { - return sanitizeName(camelize(property.name)) + "Enum"; - } - - @Override - public String toEnumVarName(String value, String datatype) { - if (value.length() == 0) { - return "EMPTY"; - } - - // for symbol, e.g. $, # - if (getSymbolName(value) != null) { - return getSymbolName(value).toUpperCase(); - } - - // number - if ("Integer".equals(datatype) || "Long".equals(datatype) || "Float".equals(datatype) - || "Double".equals(datatype)) { - String varName = "NUMBER_" + value; - varName = varName.replace("-", "MINUS_"); - varName = varName.replace("\\+", "PLUS_"); - varName = varName.replace("\\.", "_DOT_"); - return varName; - } - - // string - String var = value.replace("\\W+", "_").toUpperCase(); - if (var.matches("\\d.*")) { - return "_" + var; - } else { - return var; - } - } - - @Override - public String toEnumValue(String value, String datatype) { - if ("Integer".equals(datatype) || "Long".equals(datatype) || "Double".equals(datatype)) { - return value; - } else if ("Float".equals(datatype)) { - // add f to number, e.g. 3.14 => 3.14f - return value + "f"; - } else { - return "\"" + escapeText(value) + "\""; - } - } - - @Override - public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, - Map definitions, Swagger swagger) { - CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); - op.path = sanitizePath(op.path); - return op; - } - - @Override - public String escapeQuotationMark(String input) { - // remove " to avoid code injection - return input.replace("\"", ""); - } - - @Override - public String escapeUnsafeCharacters(String input) { - return input.replace("*/", "*_/").replace("/*", "/_*"); - } - - public boolean convertPropertyToBoolean(String propertyKey) { - boolean booleanValue = false; - if (additionalProperties.containsKey(propertyKey)) { - booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString()); - } - - return booleanValue; - } - - public String toRegularExpression(String pattern) { - return escapeText(pattern); - } - - @Override - public String sanitizeTag(String tag) { - return camelize(sanitizeName(tag)); - } - - public String toBooleanGetter(String name) { - return "is" + getterAndSetterCapitalize(name); - } - public String getGroupId() { return groupId; } @@ -1432,19 +805,6 @@ public void setWithXml(boolean withXml) { this.withXml = withXml; } - private boolean startsWithTwoUppercaseLetters(String name) { - boolean startsWithTwoUppercaseLetters = false; - if (name.length() > 1) { - startsWithTwoUppercaseLetters = name.substring(0, 2).equals(name.substring(0, 2).toUpperCase()); - } - return startsWithTwoUppercaseLetters; - } - - private String sanitizePath(String p) { - // prefer replace a ", instead of a fuLL URL encode for readability - return p.replace("\"", "%22"); - } - private interface DataTypeAssigner { void setReturnType(String returnType); diff --git a/modules/swagger-codegen/src/main/resources/pkmst/apiException.mustache b/modules/swagger-codegen/src/main/resources/pkmst/apiException.mustache deleted file mode 100644 index f6161147700..00000000000 --- a/modules/swagger-codegen/src/main/resources/pkmst/apiException.mustache +++ /dev/null @@ -1,10 +0,0 @@ -package {{apiPackage}}; - -{{>generatedAnnotation}} -public class ApiException extends Exception{ - private int code; - public ApiException (int code, String msg) { - super(msg); - this.code = code; - } -} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/apiOriginFilter.mustache b/modules/swagger-codegen/src/main/resources/pkmst/apiOriginFilter.mustache deleted file mode 100644 index 5cf72a7dc42..00000000000 --- a/modules/swagger-codegen/src/main/resources/pkmst/apiOriginFilter.mustache +++ /dev/null @@ -1,27 +0,0 @@ -package {{apiPackage}}; - -import java.io.IOException; - -import javax.servlet.*; -import javax.servlet.http.HttpServletResponse; - -{{>generatedAnnotation}} -public class ApiOriginFilter implements javax.servlet.Filter { - @Override - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain chain) throws IOException, ServletException { - HttpServletResponse res = (HttpServletResponse) response; - res.addHeader("Access-Control-Allow-Origin", "*"); - res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); - res.addHeader("Access-Control-Allow-Headers", "Content-Type"); - chain.doFilter(request, response); - } - - @Override - public void destroy() { - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } -} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/apiResponseMessage.mustache b/modules/swagger-codegen/src/main/resources/pkmst/apiResponseMessage.mustache deleted file mode 100644 index 17b155f3b69..00000000000 --- a/modules/swagger-codegen/src/main/resources/pkmst/apiResponseMessage.mustache +++ /dev/null @@ -1,69 +0,0 @@ -package {{apiPackage}}; - -import javax.xml.bind.annotation.XmlTransient; - -{{>generatedAnnotation}} -@javax.xml.bind.annotation.XmlRootElement -public class ApiResponseMessage { - public static final int ERROR = 1; - public static final int WARNING = 2; - public static final int INFO = 3; - public static final int OK = 4; - public static final int TOO_BUSY = 5; - - int code; - String type; - String message; - - public ApiResponseMessage(){} - - public ApiResponseMessage(int code, String message){ - this.code = code; - switch(code){ - case ERROR: - setType("error"); - break; - case WARNING: - setType("warning"); - break; - case INFO: - setType("info"); - break; - case OK: - setType("ok"); - break; - case TOO_BUSY: - setType("too busy"); - break; - default: - setType("unknown"); - break; - } - this.message = message; - } - - @XmlTransient - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/api_doc.mustache b/modules/swagger-codegen/src/main/resources/pkmst/api_doc.mustache deleted file mode 100644 index bbb5b66f840..00000000000 --- a/modules/swagger-codegen/src/main/resources/pkmst/api_doc.mustache +++ /dev/null @@ -1,82 +0,0 @@ -# {{classname}}{{#description}} -{{description}}{{/description}} - -All URIs are relative to *{{basePath}}* - -Method | HTTP request | Description -------------- | ------------- | ------------- -{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} -{{/operation}}{{/operations}} - -{{#operations}} -{{#operation}} - -# **{{operationId}}** -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) - -{{summary}}{{#notes}} - -{{notes}}{{/notes}} - -### Example -```java -// Import classes:{{#hasAuthMethods}} -//import {{{invokerPackage}}}.ApiClient;{{/hasAuthMethods}} -//import {{{invokerPackage}}}.ApiException;{{#hasAuthMethods}} -//import {{{invokerPackage}}}.Configuration; -//import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} -//import {{{package}}}.{{{classname}}}; - -{{#hasAuthMethods}} -ApiClient defaultClient = Configuration.getDefaultApiClient(); -{{#authMethods}}{{#isBasic}} -// Configure HTTP basic authorization: {{{name}}} -HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); -{{{name}}}.setUsername("YOUR USERNAME"); -{{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} -// Configure API key authorization: {{{name}}} -ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); -{{{name}}}.setApiKey("YOUR API KEY"); -// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) -//{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} -// Configure OAuth2 access token for authorization: {{{name}}} -OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); -{{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} -{{/authMethods}} -{{/hasAuthMethods}} - -{{{classname}}} apiInstance = new {{{classname}}}(); -{{#allParams}} -{{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} -{{/allParams}} -try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} - System.out.println(result);{{/returnType}} -} catch (ApiException e) { - System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); - e.printStackTrace(); -} -``` - -### Parameters -{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} -Name | Type | Description | Notes -------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} -{{/allParams}} - -### Return type - -{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} - -### Authorization - -{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} - -### HTTP request headers - - - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} - -{{/operation}} -{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/model_doc.mustache b/modules/swagger-codegen/src/main/resources/pkmst/model_doc.mustache deleted file mode 100644 index 658df8d5322..00000000000 --- a/modules/swagger-codegen/src/main/resources/pkmst/model_doc.mustache +++ /dev/null @@ -1,3 +0,0 @@ -{{#models}}{{#model}} -{{#isEnum}}{{>enum_outer_doc}}{{/isEnum}}{{^isEnum}}{{>pojo_doc}}{{/isEnum}} -{{/model}}{{/models}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pojo_doc.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pojo_doc.mustache deleted file mode 100644 index 0e4c0749866..00000000000 --- a/modules/swagger-codegen/src/main/resources/pkmst/pojo_doc.mustache +++ /dev/null @@ -1,15 +0,0 @@ -# {{classname}} - -## Properties -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} -{{/vars}} -{{#vars}}{{#isEnum}} - - -## Enum: {{datatypeWithEnum}} -Name | Value ----- | -----{{#allowableValues}}{{#enumVars}} -{{name}} | {{value}}{{/enumVars}}{{/allowableValues}} -{{/isEnum}}{{/vars}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache index d1f7c311ea9..16156cb63fa 100644 --- a/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache +++ b/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache @@ -260,6 +260,11 @@ org.springframework spring-test + + org.threeten + threetenbp + 1.3.6 + From d1c26540414e2069314db40c949b74ffc738de69 Mon Sep 17 00:00:00 2001 From: sanshuman Date: Tue, 12 Dec 2017 17:45:47 +0530 Subject: [PATCH 13/19] Added the script files and rectified the errors --- bin/java-petstore-pkmst-server.sh | 34 +++++++++++++++ bin/windows/java-petstore-pkmst-server.bat | 10 +++++ .../languages/JavaPKMSTServerCodegen.java | 1 + .../resources/pkmst/beanValidation.mustache | 6 +++ .../pkmst/beanValidationPathParams.mustache | 1 + .../pkmst/beanValidationQueryParams.mustache | 1 + .../resources/pkmst/enumOuterClass.mustache | 42 +++++++++++++++++++ .../resources/pkmst/implicitHeader.mustache | 1 + 8 files changed, 96 insertions(+) create mode 100644 bin/java-petstore-pkmst-server.sh create mode 100644 bin/windows/java-petstore-pkmst-server.bat create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/beanValidation.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/beanValidationPathParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/beanValidationQueryParams.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/enumOuterClass.mustache create mode 100644 modules/swagger-codegen/src/main/resources/pkmst/implicitHeader.mustache diff --git a/bin/java-petstore-pkmst-server.sh b/bin/java-petstore-pkmst-server.sh new file mode 100644 index 00000000000..3f95c1f7343 --- /dev/null +++ b/bin/java-petstore-pkmst-server.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/pkmst -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l pkmst -o samples/server/petstore/java-pkmst/ -DhideGenerationTimestamp=true" + +echo "Removing files and folders under samples/server/petstore/java-pkmst/src/main" +rm -rf samples/server/petstore/java-pkmst/src/main +find samples/server/petstore/java-pkmst -maxdepth 1 -type f ! -name "README.md" ! -name "pom.xml" ! -name "mvn_test_jdk8_only.sh" ! -name ".swagger-codegen-ignore" -exec rm {} + +java $JAVA_OPTS -jar $executable $ags diff --git a/bin/windows/java-petstore-pkmst-server.bat b/bin/windows/java-petstore-pkmst-server.bat new file mode 100644 index 00000000000..460526b4813 --- /dev/null +++ b/bin/windows/java-petstore-pkmst-server.bat @@ -0,0 +1,10 @@ +set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar + +If Not Exist %executable% ( + mvn clean package +) + +REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M +set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore.yaml -l pkmst -o samples\server\petstore\pkmst + +java %JAVA_OPTS% -jar %executable% %ags% \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java index bba08e23529..82e418bb378 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java @@ -69,6 +69,7 @@ public JavaPKMSTServerCodegen() { apiPackage = "com.prokarma.pkmst.controller"; modelPackage = "com.prokarma.pkmst.model"; invokerPackage = "com.prokarma.pkmst.controller"; + additionalProperties.put("jackson", "true"); this.cliOptions.add(new CliOption("groupId", "groupId in generated pom.xml")); this.cliOptions.add(new CliOption("artifactId", "artifactId in generated pom.xml")); this.cliOptions.add(new CliOption("artifactVersion", "artifact version in generated pom.xml")); diff --git a/modules/swagger-codegen/src/main/resources/pkmst/beanValidation.mustache b/modules/swagger-codegen/src/main/resources/pkmst/beanValidation.mustache new file mode 100644 index 00000000000..3e4ef612a4c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/beanValidation.mustache @@ -0,0 +1,6 @@ +{{#required}} + @NotNull +{{/required}}{{#isContainer}}{{^isPrimitiveType}}{{^isEnum}} + @Valid{{/isEnum}}{{/isPrimitiveType}}{{/isContainer}}{{#isNotContainer}}{{^isPrimitiveType}} + @Valid{{/isPrimitiveType}}{{/isNotContainer}} +{{>beanValidationCore}} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/beanValidationPathParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/beanValidationPathParams.mustache new file mode 100644 index 00000000000..051bd53c0a5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/beanValidationPathParams.mustache @@ -0,0 +1 @@ +{{! PathParam is always required, no @NotNull necessary }}{{>beanValidationCore}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/beanValidationQueryParams.mustache b/modules/swagger-codegen/src/main/resources/pkmst/beanValidationQueryParams.mustache new file mode 100644 index 00000000000..9cca8cb8874 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/beanValidationQueryParams.mustache @@ -0,0 +1 @@ +{{#required}}@NotNull {{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/enumOuterClass.mustache b/modules/swagger-codegen/src/main/resources/pkmst/enumOuterClass.mustache new file mode 100644 index 00000000000..76c2cbf5a76 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/enumOuterClass.mustache @@ -0,0 +1,42 @@ +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonCreator; +{{/jackson}} + +/** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} + */ +public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { + {{#gson}} + {{#allowableValues}}{{#enumVars}} + @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + {{/gson}} + {{^gson}} + {{#allowableValues}}{{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + {{/gson}} + + private {{{dataType}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } +} diff --git a/modules/swagger-codegen/src/main/resources/pkmst/implicitHeader.mustache b/modules/swagger-codegen/src/main/resources/pkmst/implicitHeader.mustache new file mode 100644 index 00000000000..64d7af20808 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/pkmst/implicitHeader.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@ApiImplicitParam(name = "{{{paramName}}}", value = "{{{description}}}", {{#required}}required=true,{{/required}} dataType = "{{{dataType}}}", paramType = "header"){{#hasMore}},{{/hasMore}}{{/isHeaderParam}} \ No newline at end of file From 5bc164fe3188992cef26eb8b7d242cba3a5b53a9 Mon Sep 17 00:00:00 2001 From: sanshuman Date: Thu, 14 Dec 2017 17:48:05 +0530 Subject: [PATCH 14/19] folder name changed and commons -lang3 version upgraded --- bin/windows/java-petstore-pkmst-server.bat | 2 +- modules/swagger-codegen/src/main/resources/pkmst/pom.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/windows/java-petstore-pkmst-server.bat b/bin/windows/java-petstore-pkmst-server.bat index 460526b4813..a8e6669b943 100644 --- a/bin/windows/java-petstore-pkmst-server.bat +++ b/bin/windows/java-petstore-pkmst-server.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore.yaml -l pkmst -o samples\server\petstore\pkmst +set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore.yaml -l pkmst -o samples\server\petstore\java-pkmst java %JAVA_OPTS% -jar %executable% %ags% \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache b/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache index 16156cb63fa..7af313005e9 100644 --- a/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache +++ b/modules/swagger-codegen/src/main/resources/pkmst/pom.mustache @@ -161,7 +161,7 @@ org.apache.commons commons-lang3 - 3.4 + 3.6 commons-logging From 741c72a05fee8357b344355ea575aae76a3434c9 Mon Sep 17 00:00:00 2001 From: sanshuman Date: Thu, 14 Dec 2017 19:18:05 +0530 Subject: [PATCH 15/19] updated readme.mustache --- .../swagger-codegen/src/main/resources/pkmst/readme.mustache | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache index 27d8199c6f7..0608438c141 100644 --- a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache +++ b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache @@ -99,6 +99,8 @@ interceptor: For testing we have placeholders for junit test class, integration test class, cucumber sample feature file(implement according to your needs), gatling load test. +Logstash: Logstash is a tool to collect, process, and forward events and log messages.Sample Logstash configuration file provided that developer can configure to collect wide variety of data.Logstash can dynamically unify data from disparate sources and normalize the data into destinations of their choice. + Ways to run the project: 1) Normal spring boot application From 598df2415c7689ef5d6df270c4f1e78cc411593f Mon Sep 17 00:00:00 2001 From: sanshuman Date: Fri, 15 Dec 2017 20:06:42 +0530 Subject: [PATCH 16/19] updated logging filter --- .../resources/pkmst/logging/httpLoggingFilter.mustache | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache b/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache index 5e09dd6090d..de21a130b46 100644 --- a/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache +++ b/modules/swagger-codegen/src/main/resources/pkmst/logging/httpLoggingFilter.mustache @@ -28,7 +28,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; - +import java.util.Arrays; import org.apache.commons.io.output.TeeOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,7 +80,11 @@ public class HttpLoggingFilter implements Filter { .append(bufferedResponse.getStatus()) .append("] [Response Time(ms):").append(elapsedTime) .append("]"); - log.info(logMessage.toString()); + String [] nonLoggingPaths = {"/v2/api-docs","/swagger-resources","/configuration/security","/swagger-ui.html","/webjars"}; + String urlPath = httpServletRequest.getRequestURL().toString(); + if (! ( Arrays.stream(nonLoggingPaths).parallel().anyMatch(urlPath::contains) )){ + log.info(logMessage.toString()); + } } catch (Throwable a) { log.error(a.getMessage()); a.printStackTrace(); From 326c8644e0934796876c1fe6616fc2dde4724876 Mon Sep 17 00:00:00 2001 From: rkumar-pk Date: Mon, 18 Dec 2017 15:13:58 +0530 Subject: [PATCH 17/19] Added petstore to samples and updated the pom for the same --- .../languages/JavaPKMSTServerCodegen.java | 1 - pom.xml | 1 + .../java-pkmst/.swagger-codegen-ignore | 23 + .../java-pkmst/.swagger-codegen/VERSION | 1 + samples/server/petstore/java-pkmst/Dockerfile | 3 + samples/server/petstore/java-pkmst/Readme.md | 142 ++++++ .../server/petstore/java-pkmst/logstash.conf | 35 ++ .../server/petstore/java-pkmst/manifest.yml | 12 + samples/server/petstore/java-pkmst/pom.xml | 416 +++++++++++++++++ .../com/prokarma/pkmst/PkmstApplication.java | 30 ++ .../com/prokarma/pkmst/config/AppConfig.java | 34 ++ .../pkmst/config/swagger/PkmstProperties.java | 113 +++++ .../swagger/SwaggerDocumentationConfig.java | 61 +++ .../com/prokarma/pkmst/controller/PetApi.java | 153 ++++++ .../pkmst/controller/PetApiController.java | 126 +++++ .../prokarma/pkmst/controller/StoreApi.java | 75 +++ .../pkmst/controller/StoreApiController.java | 85 ++++ .../prokarma/pkmst/controller/UserApi.java | 110 +++++ .../pkmst/controller/UserApiController.java | 106 +++++ .../pkmst/logging/HttpLoggingFilter.java | 434 ++++++++++++++++++ .../com/prokarma/pkmst/model/Category.java | 104 +++++ .../pkmst/model/ModelApiResponse.java | 127 +++++ .../java/com/prokarma/pkmst/model/Order.java | 231 ++++++++++ .../java/com/prokarma/pkmst/model/Pet.java | 249 ++++++++++ .../java/com/prokarma/pkmst/model/Tag.java | 104 +++++ .../java/com/prokarma/pkmst/model/User.java | 242 ++++++++++ .../AuthorizationServerConfiguration.java | 61 +++ .../security/OAuth2SecurityConfiguration.java | 82 ++++ .../security/ResourceServerConfiguration.java | 52 +++ .../main/resources/application-dev-config.yml | 7 + .../src/main/resources/application-dev.yml | 48 ++ .../src/main/resources/application-local.yml | 49 ++ .../src/main/resources/bootstrap.yml | 5 + .../prokarma/pkmst/controller/PetApiTest.java | 177 +++++++ .../prokarma/pkmst/controller/PkmstIT.java | 34 ++ .../pkmst/controller/StoreApiTest.java | 106 +++++ .../pkmst/controller/UserApiTest.java | 172 +++++++ .../prokarma/pkmst/cucumber/PkmstSteps.java | 76 +++ .../prokarma/pkmst/cucumber/PkmstTest.java | 16 + .../pkmst/cucumber/Pkmstpackage-info.java | 2 + .../pkmst/cucumber/report/ExecuteReport.java | 64 +++ .../resources/application-test.properties | 1 + .../src/test/resources/application.conf | 14 + .../src/test/resources/application.properties | 1 + .../src/test/resources/bootstrap.yml | 5 + .../com/prokarma/pkmst/cucumber/Pkmst.feature | 33 ++ .../src/test/resources/gatling.conf | 157 +++++++ .../src/test/scala/scalaFiles/testapi.scala | 41 ++ 48 files changed, 4220 insertions(+), 1 deletion(-) create mode 100644 samples/server/petstore/java-pkmst/.swagger-codegen-ignore create mode 100644 samples/server/petstore/java-pkmst/.swagger-codegen/VERSION create mode 100644 samples/server/petstore/java-pkmst/Dockerfile create mode 100644 samples/server/petstore/java-pkmst/Readme.md create mode 100644 samples/server/petstore/java-pkmst/logstash.conf create mode 100644 samples/server/petstore/java-pkmst/manifest.yml create mode 100644 samples/server/petstore/java-pkmst/pom.xml create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/PkmstApplication.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/AppConfig.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/PkmstProperties.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/SwaggerDocumentationConfig.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApi.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApiController.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApi.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApiController.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApi.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApiController.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/logging/HttpLoggingFilter.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Category.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/ModelApiResponse.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Order.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Pet.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Tag.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/User.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/AuthorizationServerConfiguration.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/OAuth2SecurityConfiguration.java create mode 100644 samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/ResourceServerConfiguration.java create mode 100644 samples/server/petstore/java-pkmst/src/main/resources/application-dev-config.yml create mode 100644 samples/server/petstore/java-pkmst/src/main/resources/application-dev.yml create mode 100644 samples/server/petstore/java-pkmst/src/main/resources/application-local.yml create mode 100644 samples/server/petstore/java-pkmst/src/main/resources/bootstrap.yml create mode 100644 samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PetApiTest.java create mode 100644 samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PkmstIT.java create mode 100644 samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/StoreApiTest.java create mode 100644 samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/UserApiTest.java create mode 100644 samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstSteps.java create mode 100644 samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstTest.java create mode 100644 samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/Pkmstpackage-info.java create mode 100644 samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/report/ExecuteReport.java create mode 100644 samples/server/petstore/java-pkmst/src/test/resources/application-test.properties create mode 100644 samples/server/petstore/java-pkmst/src/test/resources/application.conf create mode 100644 samples/server/petstore/java-pkmst/src/test/resources/application.properties create mode 100644 samples/server/petstore/java-pkmst/src/test/resources/bootstrap.yml create mode 100644 samples/server/petstore/java-pkmst/src/test/resources/com/prokarma/pkmst/cucumber/Pkmst.feature create mode 100644 samples/server/petstore/java-pkmst/src/test/resources/gatling.conf create mode 100644 samples/server/petstore/java-pkmst/src/test/scala/scalaFiles/testapi.scala diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java index 82e418bb378..bf682626edb 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPKMSTServerCodegen.java @@ -486,7 +486,6 @@ public void preprocessSwagger(Swagger swagger) { return; } if (swagger.getTags() != null) { - System.out.println("Tags are::" + swagger.getTags()); List resourcePaths = new ArrayList<>(); for (Tag tag : swagger.getTags()) { ResourcePath resourcePath = new ResourcePath(); diff --git a/pom.xml b/pom.xml index 06e025965be..6c8cf36c2f7 100644 --- a/pom.xml +++ b/pom.xml @@ -838,6 +838,7 @@ + samples/server/petstore/java-pkmst samples/client/petstore/php/SwaggerClient-php samples/client/petstore/ruby diff --git a/samples/server/petstore/java-pkmst/.swagger-codegen-ignore b/samples/server/petstore/java-pkmst/.swagger-codegen-ignore new file mode 100644 index 00000000000..c5fa491b4c5 --- /dev/null +++ b/samples/server/petstore/java-pkmst/.swagger-codegen-ignore @@ -0,0 +1,23 @@ +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/server/petstore/java-pkmst/.swagger-codegen/VERSION b/samples/server/petstore/java-pkmst/.swagger-codegen/VERSION new file mode 100644 index 00000000000..f9f7450d135 --- /dev/null +++ b/samples/server/petstore/java-pkmst/.swagger-codegen/VERSION @@ -0,0 +1 @@ +2.3.0-SNAPSHOT \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/Dockerfile b/samples/server/petstore/java-pkmst/Dockerfile new file mode 100644 index 00000000000..57da37138f2 --- /dev/null +++ b/samples/server/petstore/java-pkmst/Dockerfile @@ -0,0 +1,3 @@ +FROM frolvlad/alpine-oraclejdk8:slim +COPY target/pkmst-microservice.jar app.jar +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/Readme.md b/samples/server/petstore/java-pkmst/Readme.md new file mode 100644 index 00000000000..27d8199c6f7 --- /dev/null +++ b/samples/server/petstore/java-pkmst/Readme.md @@ -0,0 +1,142 @@ +Dear Reader : Thanks for selecting PKMST swagger code generation toolkit for starting your microservice journey. +We believe the hard work we put into this framework will help you kick start your journey sooner and you will find it +easy to scale your service to enterprise grade. Another great thing is you don't need to enable all capabilities as you start, +but can enable as your microservice capabilities needs to be extended to meet strict enterprise standards. + +PKMST feature set. +a)Read the Swagger supplied and will create a maven project +b)Create basic controller based on rest verb and path configured in swagger +c)generate default unit test cose using junit +d)generate all needed dependency needed to run the microservice on local +e)generate a default manifest file that allows you to push code to cloudfoundry instance ( eg pcf , ibm bluemix etc) + +As you mature your knowledge with pkmst, you can leverage vendor extensions feature that will allow you to supply specific configuration +in your swagger and generate respective configuration that will +f)Allow you integrate with registry server (Example Eureka) +g)Allow you to integrate with tracing server (Example Zipkin) +h)Allow you to capture log in your microservice and send to Log management server (Ex ELK or splunk) +i)Allow you to configure Oauth2 security based authorization for your microservice + + Additonal Features + j)generate sample cucumber file and dependency to drive your Behaviour driven development. + k)generate gatling based perfromance test , which can be excuted via build pipeline like jenkins etc. + + +Working: +Using swagger specification you can convert any definition to spring boot microservice. +It has the integration with the below services: +eureka registry, zipkin , spring boot admin, circuit breaker. + +By default only the circuit breaker annotation is enabled. But one has to write the fallback method. The needed dependency for it is also been enabled. To generate the integration and +related configuration for eureka, zipkin, spring boot admin one has two options: + +1) When generating from UI one has to provide vendor extensions inside the swagger specification as below: +swagger: "2.0" +info: + description: "This is a sample Product Catalogue Server.\ + \ For this sample, you can use the api key `special-key` to test the authorization\ + \ filters." + version: "1.0.0" + x-codegen: + eurekaUri: "http://localhost:8080" + zipkinUri: "http://localhost:9411" + springBootAdminUri: "http://localhost:8000" + pkmstInterceptor: "true" + +PLease note the vendor extensions are inside the info tag of the swagger specification. All the tags are case sensitive. Once given all the related configuration and the dependency +will be enabled. + +2) When generating from the maven plugin one has to provide configuration inside pom as below: +inside the swagger codegen maven plugin under the configuration section + + + product-swagger.yaml + pkmst + ${project.build.directory}/generated-sources + + com.prokarma + product-catalogue + 1.0 + com.prokarma.pkmst + ProductCatalogue + + http://localhost:9411 + http://localhost:4588 + true + + + + The project has three profiles local, dev, dev-config which can be configured accordingly. Once you have provided the uris you can see the necessary configurations generated inside the local and the dev + yml files. dev-config is for the config server if you want to use.(also enable the dependency for the config server inside the pom) + + [Note: one has to run the zipkin, eureka, spring boot admin servers to be able to connect from the app. This project assumes that you have all the servers + up and running.] + + Also provided are the middleware handlers: + +1) traceInterceptor:is an id passed in from client and will be unique with an application context. The id will be passed into the backend and return to the consumer for transaction tracing. + +2) correlationInterceptor:generates a UUID in the first API/service and pass it to all other APIs/services in the call tree for tracking purpose. + +3) rateLimitInterceptor:is a rate limiting handler to limit number of concurrent requests on the server. Once the limit is reached, subsequent requests will be queued for later execution. The size of the queue is configurable. + +4) auditInterceptor: audit logs most important info about request and response into audit.log in JSON format with config file that controls which fields to be logged + +5) bodyInterceptor:s a body parser middleware that is responsible for parsing the content of the request based on Content-Type in the request header. + +To be able to generate the handlers and the necessary configurations one has to provide the pkmstInterceptor key inside the vendor extensions or through +the maven plugin. +Once provided all the handlers are registered in the interceptor registry and can be enabled or disabled through the configuration provided inside +the application yml as below: +interceptor: + enable: + audit: true + body: true + rateLimit: true + traceability: true + correlation: true + +For testing we have placeholders for junit test class, integration test class, cucumber sample +feature file(implement according to your needs), gatling load test. + +Ways to run the project: +1) Normal spring boot application + +2) Using Dockerfile to run in the container: +dockerfile will be generated inside the project by default. Image can be created using docker cli or through the maven plugin + + + + ... + + com.spotify + docker-maven-plugin + VERSION GOES HERE + + example + docker + + + / + ${project.build.directory} + ${project.build.finalName}.jar + + + + + ... + + + +Use manifest.yml file to push the application to the cloud. + +HttpLogging filter is provided for logging in the request and response. Can be found inside the com.prokarma.pkmst.logging package. +Spring security is also provided to secure the resources. Please modify according to your needs. + +First run: +Import the project in to the eclipse. Run the app as an spring boot application.The project will run on http://localhost:8008 +Swagger ui available on: +http://localhost:8008/swagger-ui.html +If all the configurations have been enabled(depending on the port) below are some of the URls to access: +eureka: http://localhost:8080 +zipkin: http://localhost:9411 diff --git a/samples/server/petstore/java-pkmst/logstash.conf b/samples/server/petstore/java-pkmst/logstash.conf new file mode 100644 index 00000000000..491be1e7f7c --- /dev/null +++ b/samples/server/petstore/java-pkmst/logstash.conf @@ -0,0 +1,35 @@ +input { + file { + path => "" + start_position => "beginning" + + } +} + + +filter { + # pattern matching logback pattern + grok { + + } + + +} + + + +} + +output { + # Print each event to stdout, useful for debugging. Should be commented out in production. + # Enabling 'rubydebug' codec on the stdout output will make logstash + # pretty-print the entire event as something similar to a JSON representation. + stdout { + codec => rubydebug + } + + # Sending properly parsed log events to elasticsearch + elasticsearch { + hosts => ["localhost:9200"] + } +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/manifest.yml b/samples/server/petstore/java-pkmst/manifest.yml new file mode 100644 index 00000000000..2d27f25bace --- /dev/null +++ b/samples/server/petstore/java-pkmst/manifest.yml @@ -0,0 +1,12 @@ +applications: +- name: + memory: 1G + instances: 1 + host: + buildpack: https://github.com/cloudfoundry/java-buildpack.git + path: + services: + - + - + env: + \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/pom.xml b/samples/server/petstore/java-pkmst/pom.xml new file mode 100644 index 00000000000..bdd77043a36 --- /dev/null +++ b/samples/server/petstore/java-pkmst/pom.xml @@ -0,0 +1,416 @@ + + + 4.0.0 + com.prokarma + pkmst-microservice + 1.0.0 + jar + pkmst-microservice + Demo project for Spring Boot Microservices + + UTF-8 + UTF-8 + 1.8 + 1.5.6.RELEASE + 1.2.5 + 1.2.5 + 3.10.0 + 2.6.1-SNAPSHOT + 2.6.0 + 1.7.25 + 4.11 + 1.2.3 + 1.2.3 + 2.3.0 + 2.2.4 + 3.2.2 + Camden.SR7 + 1.1.3.RELEASE + + + org.springframework.boot + spring-boot-starter-parent + 1.5.6.RELEASE + + + + + + oss-snapshots + JFrog OSS Snapshots + https://oss.jfrog.org/simple/oss-snapshot-local/ + + true + + + + central + Maven Repository Switchboard + default + http://repo1.maven.org/maven2 + + false + + + + jitpack.io + https://jitpack.io + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + org.assertj + assertj-core + + + + + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-jetty + + + + org.springframework.cloud + spring-cloud-starter-hystrix-dashboard + + + org.springframework + spring-jdbc + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + com.netflix.hystrix + hystrix-javanica + 1.4.1 + + + org.apache.commons + commons-lang3 + 3.4 + + + commons-logging + commons-logging + 1.2 + + + + info.cukes + cucumber-junit + ${cucumber-junit.version} + + + info.cukes + cucumber-java + ${cucumber-java.version} + + + info.cukes + cucumber-spring + ${cucumber-java.version} + + + net.masterthought + cucumber-reporting + ${cucumber-reporting.version} + + + com.github.tomakehurst + wiremock + 1.46 + test + + + io.springfox + springfox-swagger2 + ${springfox-swagger2} + + + io.springfox + springfox-swagger-ui + ${springfox-swagger-ui} + + + org.slf4j + slf4j-api + ${slf4j-api} + + + net.logstash.logback + logstash-logback-encoder + ${logstash-logback-encoder} + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-classic + + + org.springframework.boot + spring-boot-starter-remote-shell + + + org.jolokia + jolokia-core + + + + io.gatling.highcharts + gatling-charts-highcharts + ${gatling.version} + test + + + com.typesafe + config + 1.3.1 + + + com.jayway.restassured + rest-assured + 2.9.0 + + + org.springframework + spring-test + + + org.threeten + threetenbp + 1.3.6 + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + development + + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + + **/*CucumberTest*.java + + **/cucumber/*.java + + + + + + net.alchim31.maven + scala-maven-plugin + ${scala-maven-plugin.version} + + + + + org.springframework.boot + spring-boot-maven-plugin + + ${project.name} + + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + ${basedir}/target/coverage-reports/jacoco-unit.exec + ${basedir}/target/coverage-reports/jacoco-unit.exec + + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + test + + report + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.5.1 + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.4 + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.19.1 + + + org.apache.maven.plugins + maven-pmd-plugin + + + + + + + + + cucumber-tests + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + none + + + + Test.java + + + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.springframework.cloud + spring-cloud-contract-maven-plugin + [1.0.1.RELEASE,) + + convert + generateTests + + + + + + + + + + + + + + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/PkmstApplication.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/PkmstApplication.java new file mode 100644 index 00000000000..63d2fac6ec5 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/PkmstApplication.java @@ -0,0 +1,30 @@ +package com.prokarma.pkmst; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * starts the spring boot application + * @author pkmst + * + */ + +@SpringBootApplication +@EnableSwagger2 +@EnableCircuitBreaker +@EnableHystrixDashboard +public class PkmstApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(PkmstApplication.class); + + public static void main(String[] args) { + LOGGER.debug("Running spring boot application"); + SpringApplication.run(PkmstApplication.class, args); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/AppConfig.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/AppConfig.java new file mode 100644 index 00000000000..ba323306ce0 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/AppConfig.java @@ -0,0 +1,34 @@ +package com.prokarma.pkmst.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +/** + * Registers the interceptors which are configurable via yaml + * @author pkmst + * + */ +@Configuration +public class AppConfig extends WebMvcConfigurerAdapter { + /** + * enabling cors support at global level which can be applied at various + * level also as below registry.addMapping("/api/**") + * .allowedOrigins("http://domain2.com") .allowedMethods("PUT", "DELETE") + * .allowedHeaders("header1", "header2", "header3") + * .exposedHeaders("header1", "header2") + * .allowCredentials(false).maxAge(3600); + * + * @return + */ + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurerAdapter() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**"); + } + }; + } +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/PkmstProperties.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/PkmstProperties.java new file mode 100644 index 00000000000..6d64cd6e26a --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/PkmstProperties.java @@ -0,0 +1,113 @@ +package com.prokarma.pkmst.config.swagger; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +/** + * Provides the swagger API info + * @author pkmst + * + */ +@Configuration +@ConfigurationProperties(prefix = "pkmst", ignoreUnknownFields = false) +public class PkmstProperties { + + private final Swagger swagger = new Swagger(); + + + public Swagger getSwagger() { + return swagger; + } + + + public static class Swagger { + + private String title = "Pkmst API"; + + private String description = "Pkmst API documentation"; + + private String version = "0.0.1"; + + private String termsOfServiceUrl; + + private String contactName; + + private String contactUrl; + + private String contactEmail; + + private String license; + + private String licenseUrl; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getTermsOfServiceUrl() { + return termsOfServiceUrl; + } + + public void setTermsOfServiceUrl(String termsOfServiceUrl) { + this.termsOfServiceUrl = termsOfServiceUrl; + } + + public String getContactName() { + return contactName; + } + + public void setContactName(String contactName) { + this.contactName = contactName; + } + + public String getContactUrl() { + return contactUrl; + } + + public void setContactUrl(String contactUrl) { + this.contactUrl = contactUrl; + } + + public String getContactEmail() { + return contactEmail; + } + + public void setContactEmail(String contactEmail) { + this.contactEmail = contactEmail; + } + + public String getLicense() { + return license; + } + + public void setLicense(String license) { + this.license = license; + } + + public String getLicenseUrl() { + return licenseUrl; + } + + public void setLicenseUrl(String licenseUrl) { + this.licenseUrl = licenseUrl; + } + } +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/SwaggerDocumentationConfig.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/SwaggerDocumentationConfig.java new file mode 100644 index 00000000000..67599c9bb45 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/config/swagger/SwaggerDocumentationConfig.java @@ -0,0 +1,61 @@ +package com.prokarma.pkmst.config.swagger; + +import java.util.Date; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StopWatch; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +//import static springfox.documentation.builders.PathSelectors.regex; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; +/** + * Enable swagger ui for application + * @author pkmst + * + */ +@EnableSwagger2 +@Configuration +public class SwaggerDocumentationConfig { + + public static final String DEFAULT_INCLUDE_PATTERN = "/pkmst/.*"; + @Bean + public Docket swaggerSpringfoxDocket(PkmstProperties pkmstProperties) { + StopWatch watch = new StopWatch(); + watch.start(); + Contact contact = new Contact( + pkmstProperties.getSwagger().getContactName(), + pkmstProperties.getSwagger().getContactUrl(), + pkmstProperties.getSwagger().getContactEmail()); + + ApiInfo apiInfo = new ApiInfo( + pkmstProperties.getSwagger().getTitle(), + pkmstProperties.getSwagger().getDescription(), + pkmstProperties.getSwagger().getVersion(), + pkmstProperties.getSwagger().getTermsOfServiceUrl(), + contact, + pkmstProperties.getSwagger().getLicense(), + pkmstProperties.getSwagger().getLicenseUrl()); + + Docket docket = new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo) + .forCodeGeneration(true) + .genericModelSubstitutes(ResponseEntity.class) + .ignoredParameterTypes(java.sql.Date.class) + .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(java.time.ZonedDateTime.class, Date.class) + .directModelSubstitute(java.time.LocalDateTime.class, Date.class) + .select() + .apis(RequestHandlerSelectors.basePackage("com.prokarma.pkmst")) + // .paths(regex(DEFAULT_INCLUDE_PATTERN)) + .paths(PathSelectors.any()) + .build(); + watch.stop(); + return docket; + } + +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApi.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApi.java new file mode 100644 index 00000000000..125678b28b1 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApi.java @@ -0,0 +1,153 @@ +/** + * NOTE: This class is auto generated by the swagger code generator program (2.3.0-SNAPSHOT). + * https://github.com/swagger-api/swagger-codegen + * Do not edit the class manually. + */ +package com.prokarma.pkmst.controller; + +import java.io.File; +import com.prokarma.pkmst.model.ModelApiResponse; +import com.prokarma.pkmst.model.Pet; + +import io.swagger.annotations.*; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; + +import java.util.List; +/** + * Provides the info about api methods + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Api(value = "Pet", description = "the Pet API") +public interface PetApi { + + @ApiOperation(value = "Add a new pet to the store", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 405, message = "Invalid input") }) + @RequestMapping(value = "/pet", + produces = { "application/xml", "application/json" }, + consumes = { "application/json", "application/xml" }, + method = RequestMethod.POST) + ResponseEntity addPet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Deletes a pet", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid pet value") }) + @RequestMapping(value = "/pet/{petId}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.DELETE) + ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Finds Pets by status", notes = "Multiple status values can be provided with comma separated strings", response = Pet.class, responseContainer = "List", authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Pet.class, responseContainer = "List"), + @ApiResponse(code = 400, message = "Invalid status value") }) + @RequestMapping(value = "/pet/findByStatus", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity> findPetsByStatus(@ApiParam(value = "Status values that need to be considered for filter", required = true, allowableValues = "available, pending, sold") @RequestParam(value = "status", required = true) List status, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Finds Pets by tags", notes = "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", response = Pet.class, responseContainer = "List", authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Pet.class, responseContainer = "List"), + @ApiResponse(code = 400, message = "Invalid tag value") }) + @RequestMapping(value = "/pet/findByTags", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity> findPetsByTags(@ApiParam(value = "Tags to filter by", required = true) @RequestParam(value = "tags", required = true) List tags, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Find pet by ID", notes = "Returns a single pet", response = Pet.class, authorizations = { + @Authorization(value = "api_key") + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Pet.class), + @ApiResponse(code = 400, message = "Invalid ID supplied"), + @ApiResponse(code = 404, message = "Pet not found") }) + @RequestMapping(value = "/pet/{petId}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity getPetById(@ApiParam(value = "ID of pet to return",required=true ) @PathVariable("petId") Long petId, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Update an existing pet", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid ID supplied"), + @ApiResponse(code = 404, message = "Pet not found"), + @ApiResponse(code = 405, message = "Validation exception") }) + @RequestMapping(value = "/pet", + produces = { "application/xml", "application/json" }, + consumes = { "application/json", "application/xml" }, + method = RequestMethod.PUT) + ResponseEntity updatePet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Updates a pet in the store with form data", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 405, message = "Invalid input") }) + @RequestMapping(value = "/pet/{petId}", + produces = { "application/xml", "application/json" }, + consumes = { "application/x-www-form-urlencoded" }, + method = RequestMethod.POST) + ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Updated name of the pet") @RequestPart(value="name", required=false) String name,@ApiParam(value = "Updated status of the pet") @RequestPart(value="status", required=false) String status, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "uploads an image", notes = "", response = ModelApiResponse.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = ModelApiResponse.class) }) + @RequestMapping(value = "/pet/{petId}/uploadImage", + produces = { "application/json" }, + consumes = { "multipart/form-data" }, + method = RequestMethod.POST) + ResponseEntity uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Additional data to pass to server") @RequestPart(value="additionalMetadata", required=false) String additionalMetadata,@ApiParam(value = "file detail") @RequestPart("file") MultipartFile file, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApiController.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApiController.java new file mode 100644 index 00000000000..c8f9f82e9e6 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/PetApiController.java @@ -0,0 +1,126 @@ +package com.prokarma.pkmst.controller; + +import java.io.File; +import com.prokarma.pkmst.model.ModelApiResponse; +import com.prokarma.pkmst.model.Pet; + +import io.swagger.annotations.*; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +/** + * Api implemention + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Controller +public class PetApiController implements PetApi { + private final ObjectMapper objectMapper; +@Autowired + public PetApiController(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + public ResponseEntity addPet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId, + @ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity> findPetsByStatus(@ApiParam(value = "Status values that need to be considered for filter", required = true, allowableValues = "available, pending, sold") @RequestParam(value = "status", required = true) List status, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity>(objectMapper.readValue("", List.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity>(objectMapper.readValue("", List.class), HttpStatus.OK); + } + + return new ResponseEntity>(HttpStatus.OK); + } + + public ResponseEntity> findPetsByTags(@ApiParam(value = "Tags to filter by", required = true) @RequestParam(value = "tags", required = true) List tags, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity>(objectMapper.readValue("", List.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity>(objectMapper.readValue("", List.class), HttpStatus.OK); + } + + return new ResponseEntity>(HttpStatus.OK); + } + + public ResponseEntity getPetById(@ApiParam(value = "ID of pet to return",required=true ) @PathVariable("petId") Long petId, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", Pet.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", Pet.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity updatePet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId, + @ApiParam(value = "Updated name of the pet") @RequestPart(value="name", required=false) String name, + @ApiParam(value = "Updated status of the pet") @RequestPart(value="status", required=false) String status, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId, + @ApiParam(value = "Additional data to pass to server") @RequestPart(value="additionalMetadata", required=false) String additionalMetadata, + @ApiParam(value = "file detail") @RequestPart("file") MultipartFile file, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", ModelApiResponse.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApi.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApi.java new file mode 100644 index 00000000000..e457b0778a3 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApi.java @@ -0,0 +1,75 @@ +/** + * NOTE: This class is auto generated by the swagger code generator program (2.3.0-SNAPSHOT). + * https://github.com/swagger-api/swagger-codegen + * Do not edit the class manually. + */ +package com.prokarma.pkmst.controller; + +import java.util.Map; +import com.prokarma.pkmst.model.Order; + +import io.swagger.annotations.*; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; + +import java.util.List; +/** + * Provides the info about api methods + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Api(value = "Store", description = "the Store API") +public interface StoreApi { + + @ApiOperation(value = "Delete purchase order by ID", notes = "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", response = Void.class, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid ID supplied"), + @ApiResponse(code = 404, message = "Order not found") }) + @RequestMapping(value = "/store/order/{orderId}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.DELETE) + ResponseEntity deleteOrder(@ApiParam(value = "ID of the order that needs to be deleted",required=true ) @PathVariable("orderId") String orderId, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Returns pet inventories by status", notes = "Returns a map of status codes to quantities", response = Integer.class, responseContainer = "Map", authorizations = { + @Authorization(value = "api_key") + }, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Map.class, responseContainer = "Map") }) + @RequestMapping(value = "/store/inventory", + produces = { "application/json" }, + method = RequestMethod.GET) + ResponseEntity> getInventory( @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order.class, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Order.class), + @ApiResponse(code = 400, message = "Invalid ID supplied"), + @ApiResponse(code = 404, message = "Order not found") }) + @RequestMapping(value = "/store/order/{orderId}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathVariable("orderId") Long orderId, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Place an order for a pet", notes = "", response = Order.class, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Order.class), + @ApiResponse(code = 400, message = "Invalid Order") }) + @RequestMapping(value = "/store/order", + produces = { "application/xml", "application/json" }, + method = RequestMethod.POST) + ResponseEntity placeOrder(@ApiParam(value = "order placed for purchasing the pet" ,required=true ) @RequestBody Order body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApiController.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApiController.java new file mode 100644 index 00000000000..a34a38ce418 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/StoreApiController.java @@ -0,0 +1,85 @@ +package com.prokarma.pkmst.controller; + +import java.util.Map; +import com.prokarma.pkmst.model.Order; + +import io.swagger.annotations.*; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +/** + * Api implemention + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Controller +public class StoreApiController implements StoreApi { + private final ObjectMapper objectMapper; +@Autowired + public StoreApiController(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + public ResponseEntity deleteOrder(@ApiParam(value = "ID of the order that needs to be deleted",required=true ) @PathVariable("orderId") String orderId, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity> getInventory(@RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity>(objectMapper.readValue("", Map.class), HttpStatus.OK); + } + + return new ResponseEntity>(HttpStatus.OK); + } + + public ResponseEntity getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathVariable("orderId") Long orderId, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", Order.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", Order.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity placeOrder(@ApiParam(value = "order placed for purchasing the pet" ,required=true ) @RequestBody Order body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", Order.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", Order.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApi.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApi.java new file mode 100644 index 00000000000..4f591a67307 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApi.java @@ -0,0 +1,110 @@ +/** + * NOTE: This class is auto generated by the swagger code generator program (2.3.0-SNAPSHOT). + * https://github.com/swagger-api/swagger-codegen + * Do not edit the class manually. + */ +package com.prokarma.pkmst.controller; + +import java.util.List; +import com.prokarma.pkmst.model.User; + +import io.swagger.annotations.*; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; + +import java.util.List; +/** + * Provides the info about api methods + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Api(value = "User", description = "the User API") +public interface UserApi { + + @ApiOperation(value = "Create user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation") }) + @RequestMapping(value = "/user", + produces = { "application/xml", "application/json" }, + method = RequestMethod.POST) + ResponseEntity createUser(@ApiParam(value = "Created user object" ,required=true ) @RequestBody User body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation") }) + @RequestMapping(value = "/user/createWithArray", + produces = { "application/xml", "application/json" }, + method = RequestMethod.POST) + ResponseEntity createUsersWithArrayInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation") }) + @RequestMapping(value = "/user/createWithList", + produces = { "application/xml", "application/json" }, + method = RequestMethod.POST) + ResponseEntity createUsersWithListInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Delete user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid username supplied"), + @ApiResponse(code = 404, message = "User not found") }) + @RequestMapping(value = "/user/{username}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.DELETE) + ResponseEntity deleteUser(@ApiParam(value = "The name that needs to be deleted",required=true ) @PathVariable("username") String username, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Get user by user name", notes = "", response = User.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = User.class), + @ApiResponse(code = 400, message = "Invalid username supplied"), + @ApiResponse(code = 404, message = "User not found") }) + @RequestMapping(value = "/user/{username}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity getUserByName(@ApiParam(value = "The name that needs to be fetched. Use user1 for testing. ",required=true ) @PathVariable("username") String username, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Logs user into the system", notes = "", response = String.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = String.class), + @ApiResponse(code = 400, message = "Invalid username/password supplied") }) + @RequestMapping(value = "/user/login", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity loginUser(@ApiParam(value = "The user name for login", required = true) @RequestParam(value = "username", required = true) String username,@ApiParam(value = "The password for login in clear text", required = true) @RequestParam(value = "password", required = true) String password, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Logs out current logged in user session", notes = "", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation") }) + @RequestMapping(value = "/user/logout", + produces = { "application/xml", "application/json" }, + method = RequestMethod.GET) + ResponseEntity logoutUser( @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + + + @ApiOperation(value = "Updated user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid user supplied"), + @ApiResponse(code = 404, message = "User not found") }) + @RequestMapping(value = "/user/{username}", + produces = { "application/xml", "application/json" }, + method = RequestMethod.PUT) + ResponseEntity updateUser(@ApiParam(value = "name that need to be deleted",required=true ) @PathVariable("username") String username,@ApiParam(value = "Updated user object" ,required=true ) @RequestBody User body, @RequestHeader(value = "Accept", required = false) String accept) throws Exception; + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApiController.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApiController.java new file mode 100644 index 00000000000..65c45ee62ab --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/controller/UserApiController.java @@ -0,0 +1,106 @@ +package com.prokarma.pkmst.controller; + +import java.util.List; +import com.prokarma.pkmst.model.User; + +import io.swagger.annotations.*; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +/** + * Api implemention + * @author pkmst + * + */ +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +@Controller +public class UserApiController implements UserApi { + private final ObjectMapper objectMapper; +@Autowired + public UserApiController(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + public ResponseEntity createUser(@ApiParam(value = "Created user object" ,required=true ) @RequestBody User body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity createUsersWithArrayInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity createUsersWithListInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity deleteUser(@ApiParam(value = "The name that needs to be deleted",required=true ) @PathVariable("username") String username, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity getUserByName(@ApiParam(value = "The name that needs to be fetched. Use user1 for testing. ",required=true ) @PathVariable("username") String username, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", User.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", User.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity loginUser(@ApiParam(value = "The user name for login", required = true) @RequestParam(value = "username", required = true) String username, + @ApiParam(value = "The password for login in clear text", required = true) @RequestParam(value = "password", required = true) String password, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + + if (accept != null && accept.contains("application/xml")) { + return new ResponseEntity(objectMapper.readValue("", String.class), HttpStatus.OK); + } + + + if (accept != null && accept.contains("application/json")) { + return new ResponseEntity(objectMapper.readValue("", String.class), HttpStatus.OK); + } + + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity logoutUser(@RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + + public ResponseEntity updateUser(@ApiParam(value = "name that need to be deleted",required=true ) @PathVariable("username") String username, + @ApiParam(value = "Updated user object" ,required=true ) @RequestBody User body, + @RequestHeader(value = "Accept", required = false) String accept) throws Exception { + // do some magic! + return new ResponseEntity(HttpStatus.OK); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/logging/HttpLoggingFilter.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/logging/HttpLoggingFilter.java new file mode 100644 index 00000000000..ffb1b3e6cb5 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/logging/HttpLoggingFilter.java @@ -0,0 +1,434 @@ +package com.prokarma.pkmst.logging; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ReadListener; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.WriteListener; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.output.TeeOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +/** + * Implements javax.servlet.Filter and dump the request/response to syslog + * @author pkmst + * + */ + +@Component +public class HttpLoggingFilter implements Filter { + + private static final Logger log = LoggerFactory.getLogger(HttpLoggingFilter.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { + try { + HttpServletRequest httpServletRequest = (HttpServletRequest) request; + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + Map requestMap = this.getTypesafeRequestMap(httpServletRequest); + BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpServletRequest); + BufferedResponseWrapper bufferedResponse = new BufferedResponseWrapper(httpServletResponse); + final StringBuilder logMessage = new StringBuilder( + "REST Request - ").append("[HTTP METHOD:") + .append(httpServletRequest.getMethod()) + .append("] [PATH INFO:") + .append(httpServletRequest.getServletPath()) + .append("] [REQUEST PARAMETERS:").append(requestMap) + .append("] [REQUEST BODY:") + .append(bufferedRequest.getRequestBody()) + .append("] [REMOTE ADDRESS:") + .append(httpServletRequest.getRemoteAddr()).append("]"); + long start = System.currentTimeMillis(); + chain.doFilter(bufferedRequest, bufferedResponse); + long elapsedTime = System.currentTimeMillis() - start; + String respContent = null; + if (bufferedResponse.getContent() == null || bufferedResponse.getContent() == "") { + respContent = "No data"; + } else { + respContent = bufferedResponse.getContent(); + } + logMessage.append(" [RESPONSE:").append(respContent) + .append("] [STATUS CODE:") + .append(bufferedResponse.getStatus()) + .append("] [Response Time(ms):").append(elapsedTime) + .append("]"); + log.info(logMessage.toString()); + } catch (Throwable a) { + log.error(a.getMessage()); + a.printStackTrace(); + } + } + + private Map getTypesafeRequestMap(HttpServletRequest request) { + Map typesafeRequestMap = new HashMap(); + Enumeration requestParamNames = request.getParameterNames(); + while (requestParamNames.hasMoreElements()) { + String requestParamName = (String) requestParamNames.nextElement(); + String requestParamValue; + if (requestParamName.equalsIgnoreCase("password")) { + requestParamValue = "********"; + } else { + requestParamValue = request.getParameter(requestParamName); + } + typesafeRequestMap.put(requestParamName, requestParamValue); + } + return typesafeRequestMap; + } + + @Override + public void destroy() { + } + + private static final class BufferedRequestWrapper extends HttpServletRequestWrapper { + + private ByteArrayInputStream bais = null; + private ByteArrayOutputStream baos = null; + private BufferedServletInputStream bsis = null; + private byte[] buffer = null; + + public BufferedRequestWrapper(HttpServletRequest req) throws IOException { + super(req); + // Read InputStream and store its content in a buffer. + InputStream is = req.getInputStream(); + this.baos = new ByteArrayOutputStream(); + byte buf[] = new byte[1024]; + int read; + while ((read = is.read(buf)) > 0) { + this.baos.write(buf, 0, read); + } + this.buffer = this.baos.toByteArray(); + } + + @Override + public ServletInputStream getInputStream() { + this.bais = new ByteArrayInputStream(this.buffer); + this.bsis = new BufferedServletInputStream(this.bais); + return this.bsis; + } + + String getRequestBody() throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(this.getInputStream())); + String line = null; + StringBuilder inputBuffer = new StringBuilder(); + do { + line = reader.readLine(); + if (null != line) { + inputBuffer.append(line.trim()); + } + } while (line != null); + reader.close(); + return inputBuffer.toString().trim(); + } + + } + + private static final class BufferedServletInputStream extends ServletInputStream { + + private ByteArrayInputStream bais; + + public BufferedServletInputStream(ByteArrayInputStream bais) { + this.bais = bais; + } + + @Override + public int available() { + return this.bais.available(); + } + + @Override + public int read() { + return this.bais.read(); + } + + @Override + public int read(byte[] buf, int off, int len) { + return this.bais.read(buf, off, len); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + } + + public class TeeServletOutputStream extends ServletOutputStream { + + private final TeeOutputStream targetStream; + + public TeeServletOutputStream(OutputStream one, OutputStream two) { + targetStream = new TeeOutputStream(one, two); + } + + @Override + public void write(int arg0) throws IOException { + this.targetStream.write(arg0); + } + + public void flush() throws IOException { + super.flush(); + this.targetStream.flush(); + } + + public void close() throws IOException { + super.close(); + this.targetStream.close(); + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + + } + } + + public class BufferedResponseWrapper implements HttpServletResponse { + + HttpServletResponse original; + TeeServletOutputStream tee; + ByteArrayOutputStream bos; + + public BufferedResponseWrapper(HttpServletResponse response) { + original = response; + } + + public String getContent() { + if (bos == null) { + return null; + } else + return bos.toString(); + } + + public PrintWriter getWriter() throws IOException { + return original.getWriter(); + } + + public ServletOutputStream getOutputStream() throws IOException { + if (tee == null) { + bos = new ByteArrayOutputStream(); + tee = new TeeServletOutputStream(original.getOutputStream(),bos); + } + return tee; + + } + + @Override + public String getCharacterEncoding() { + return original.getCharacterEncoding(); + } + + @Override + public String getContentType() { + return original.getContentType(); + } + + @Override + public void setCharacterEncoding(String charset) { + original.setCharacterEncoding(charset); + } + + @Override + public void setContentLength(int len) { + original.setContentLength(len); + } + + @Override + public void setContentLengthLong(long l) { + original.setContentLengthLong(l); + } + + @Override + public void setContentType(String type) { + original.setContentType(type); + } + + @Override + public void setBufferSize(int size) { + original.setBufferSize(size); + } + + @Override + public int getBufferSize() { + return original.getBufferSize(); + } + + @Override + public void flushBuffer() throws IOException { + tee.flush(); + } + + @Override + public void resetBuffer() { + original.resetBuffer(); + } + + @Override + public boolean isCommitted() { + return original.isCommitted(); + } + + @Override + public void reset() { + original.reset(); + } + + @Override + public void setLocale(Locale loc) { + original.setLocale(loc); + } + + @Override + public Locale getLocale() { + return original.getLocale(); + } + + @Override + public void addCookie(Cookie cookie) { + original.addCookie(cookie); + } + + @Override + public boolean containsHeader(String name) { + return original.containsHeader(name); + } + + @Override + public String encodeURL(String url) { + return original.encodeURL(url); + } + + @Override + public String encodeRedirectURL(String url) { + return original.encodeRedirectURL(url); + } + + @SuppressWarnings("deprecation") + @Override + public String encodeUrl(String url) { + return original.encodeUrl(url); + } + + @SuppressWarnings("deprecation") + @Override + public String encodeRedirectUrl(String url) { + return original.encodeRedirectUrl(url); + } + + @Override + public void sendError(int sc, String msg) throws IOException { + original.sendError(sc, msg); + } + + @Override + public void sendError(int sc) throws IOException { + original.sendError(sc); + } + + @Override + public void sendRedirect(String location) throws IOException { + original.sendRedirect(location); + } + + @Override + public void setDateHeader(String name, long date) { + original.setDateHeader(name, date); + } + + @Override + public void addDateHeader(String name, long date) { + original.addDateHeader(name, date); + } + + @Override + public void setHeader(String name, String value) { + original.setHeader(name, value); + } + + @Override + public void addHeader(String name, String value) { + original.addHeader(name, value); + } + + @Override + public void setIntHeader(String name, int value) { + original.setIntHeader(name, value); + } + + @Override + public void addIntHeader(String name, int value) { + original.addIntHeader(name, value); + } + + @Override + public void setStatus(int sc) { + original.setStatus(sc); + } + + @SuppressWarnings("deprecation") + @Override + public void setStatus(int sc, String sm) { + original.setStatus(sc, sm); + } + + @Override + public String getHeader(String arg0) { + return original.getHeader(arg0); + } + + @Override + public Collection getHeaderNames() { + return original.getHeaderNames(); + } + + @Override + public Collection getHeaders(String arg0) { + return original.getHeaders(arg0); + } + + @Override + public int getStatus() { + return original.getStatus(); + } + } +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Category.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Category.java new file mode 100644 index 00000000000..2d27297d3de --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Category.java @@ -0,0 +1,104 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * A category for a pet + */ +@ApiModel(description = "A category for a pet") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class Category { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("name") + private String name = null; + + public Category id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Category name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @ApiModelProperty(value = "") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Category category = (Category) o; + return Objects.equals(this.id, category.id) && + Objects.equals(this.name, category.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Category {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/ModelApiResponse.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/ModelApiResponse.java new file mode 100644 index 00000000000..7a2ca9b4c95 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/ModelApiResponse.java @@ -0,0 +1,127 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * Describes the result of uploading an image resource + */ +@ApiModel(description = "Describes the result of uploading an image resource") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class ModelApiResponse { + @JsonProperty("code") + private Integer code = null; + + @JsonProperty("type") + private String type = null; + + @JsonProperty("message") + private String message = null; + + public ModelApiResponse code(Integer code) { + this.code = code; + return this; + } + + /** + * Get code + * @return code + **/ + @ApiModelProperty(value = "") + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public ModelApiResponse type(String type) { + this.type = type; + return this; + } + + /** + * Get type + * @return type + **/ + @ApiModelProperty(value = "") + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public ModelApiResponse message(String message) { + this.message = message; + return this; + } + + /** + * Get message + * @return message + **/ + @ApiModelProperty(value = "") + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ModelApiResponse _apiResponse = (ModelApiResponse) o; + return Objects.equals(this.code, _apiResponse.code) && + Objects.equals(this.type, _apiResponse.type) && + Objects.equals(this.message, _apiResponse.message); + } + + @Override + public int hashCode() { + return Objects.hash(code, type, message); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ModelApiResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Order.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Order.java new file mode 100644 index 00000000000..70432b68f31 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Order.java @@ -0,0 +1,231 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.threeten.bp.OffsetDateTime; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * An order for a pets from the pet store + */ +@ApiModel(description = "An order for a pets from the pet store") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class Order { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("petId") + private Long petId = null; + + @JsonProperty("quantity") + private Integer quantity = null; + + @JsonProperty("shipDate") + private OffsetDateTime shipDate = null; + + /** + * Order Status + */ + public enum StatusEnum { + PLACED("placed"), + + APPROVED("approved"), + + DELIVERED("delivered"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static StatusEnum fromValue(String text) { + for (StatusEnum b : StatusEnum.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } + } + + @JsonProperty("status") + private StatusEnum status = null; + + @JsonProperty("complete") + private Boolean complete = false; + + public Order id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Order petId(Long petId) { + this.petId = petId; + return this; + } + + /** + * Get petId + * @return petId + **/ + @ApiModelProperty(value = "") + public Long getPetId() { + return petId; + } + + public void setPetId(Long petId) { + this.petId = petId; + } + + public Order quantity(Integer quantity) { + this.quantity = quantity; + return this; + } + + /** + * Get quantity + * @return quantity + **/ + @ApiModelProperty(value = "") + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + public Order shipDate(OffsetDateTime shipDate) { + this.shipDate = shipDate; + return this; + } + + /** + * Get shipDate + * @return shipDate + **/ + @ApiModelProperty(value = "") + public OffsetDateTime getShipDate() { + return shipDate; + } + + public void setShipDate(OffsetDateTime shipDate) { + this.shipDate = shipDate; + } + + public Order status(StatusEnum status) { + this.status = status; + return this; + } + + /** + * Order Status + * @return status + **/ + @ApiModelProperty(value = "Order Status") + public StatusEnum getStatus() { + return status; + } + + public void setStatus(StatusEnum status) { + this.status = status; + } + + public Order complete(Boolean complete) { + this.complete = complete; + return this; + } + + /** + * Get complete + * @return complete + **/ + @ApiModelProperty(value = "") + public Boolean isComplete() { + return complete; + } + + public void setComplete(Boolean complete) { + this.complete = complete; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Order order = (Order) o; + return Objects.equals(this.id, order.id) && + Objects.equals(this.petId, order.petId) && + Objects.equals(this.quantity, order.quantity) && + Objects.equals(this.shipDate, order.shipDate) && + Objects.equals(this.status, order.status) && + Objects.equals(this.complete, order.complete); + } + + @Override + public int hashCode() { + return Objects.hash(id, petId, quantity, shipDate, status, complete); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Order {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" petId: ").append(toIndentedString(petId)).append("\n"); + sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n"); + sb.append(" shipDate: ").append(toIndentedString(shipDate)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" complete: ").append(toIndentedString(complete)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Pet.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Pet.java new file mode 100644 index 00000000000..9d56722e870 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Pet.java @@ -0,0 +1,249 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.prokarma.pkmst.model.Category; +import com.prokarma.pkmst.model.Tag; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * A pet for sale in the pet store + */ +@ApiModel(description = "A pet for sale in the pet store") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class Pet { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("category") + private Category category = null; + + @JsonProperty("name") + private String name = null; + + @JsonProperty("photoUrls") + + private List photoUrls = new ArrayList<>(); + + @JsonProperty("tags") + + private List tags = null; + + /** + * pet status in the store + */ + public enum StatusEnum { + AVAILABLE("available"), + + PENDING("pending"), + + SOLD("sold"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static StatusEnum fromValue(String text) { + for (StatusEnum b : StatusEnum.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } + } + + @JsonProperty("status") + private StatusEnum status = null; + + public Pet id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Pet category(Category category) { + this.category = category; + return this; + } + + /** + * Get category + * @return category + **/ + @ApiModelProperty(value = "") + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } + + public Pet name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @ApiModelProperty(example = "doggie", required = true, value = "") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Pet photoUrls(List photoUrls) { + this.photoUrls = photoUrls; + return this; + } + + public Pet addPhotoUrlsItem(String photoUrlsItem) { + this.photoUrls.add(photoUrlsItem); + return this; + } + + /** + * Get photoUrls + * @return photoUrls + **/ + @ApiModelProperty(required = true, value = "") + public List getPhotoUrls() { + return photoUrls; + } + + public void setPhotoUrls(List photoUrls) { + this.photoUrls = photoUrls; + } + + public Pet tags(List tags) { + this.tags = tags; + return this; + } + + public Pet addTagsItem(Tag tagsItem) { + if (this.tags == null) { + this.tags = new ArrayList<>(); + } + this.tags.add(tagsItem); + return this; + } + + /** + * Get tags + * @return tags + **/ + @ApiModelProperty(value = "") + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public Pet status(StatusEnum status) { + this.status = status; + return this; + } + + /** + * pet status in the store + * @return status + **/ + @ApiModelProperty(value = "pet status in the store") + public StatusEnum getStatus() { + return status; + } + + public void setStatus(StatusEnum status) { + this.status = status; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Pet pet = (Pet) o; + return Objects.equals(this.id, pet.id) && + Objects.equals(this.category, pet.category) && + Objects.equals(this.name, pet.name) && + Objects.equals(this.photoUrls, pet.photoUrls) && + Objects.equals(this.tags, pet.tags) && + Objects.equals(this.status, pet.status); + } + + @Override + public int hashCode() { + return Objects.hash(id, category, name, photoUrls, tags, status); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Pet {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" category: ").append(toIndentedString(category)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" photoUrls: ").append(toIndentedString(photoUrls)).append("\n"); + sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Tag.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Tag.java new file mode 100644 index 00000000000..ae1b34a856f --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/Tag.java @@ -0,0 +1,104 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * A tag for a pet + */ +@ApiModel(description = "A tag for a pet") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class Tag { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("name") + private String name = null; + + public Tag id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Tag name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + **/ + @ApiModelProperty(value = "") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tag tag = (Tag) o; + return Objects.equals(this.id, tag.id) && + Objects.equals(this.name, tag.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Tag {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/User.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/User.java new file mode 100644 index 00000000000..5633f163eb0 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/model/User.java @@ -0,0 +1,242 @@ +package com.prokarma.pkmst.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +/** + * Response class to be returned by Api + * @author pkmst + * + */ +/** + * A User who is purchasing from the pet store + */ +@ApiModel(description = "A User who is purchasing from the pet store") + +@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaPKMSTServerCodegen", date = "2017-12-18T14:05:35.281+05:30") + +public class User { + @JsonProperty("id") + private Long id = null; + + @JsonProperty("username") + private String username = null; + + @JsonProperty("firstName") + private String firstName = null; + + @JsonProperty("lastName") + private String lastName = null; + + @JsonProperty("email") + private String email = null; + + @JsonProperty("password") + private String password = null; + + @JsonProperty("phone") + private String phone = null; + + @JsonProperty("userStatus") + private Integer userStatus = null; + + public User id(Long id) { + this.id = id; + return this; + } + + /** + * Get id + * @return id + **/ + @ApiModelProperty(value = "") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public User username(String username) { + this.username = username; + return this; + } + + /** + * Get username + * @return username + **/ + @ApiModelProperty(value = "") + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public User firstName(String firstName) { + this.firstName = firstName; + return this; + } + + /** + * Get firstName + * @return firstName + **/ + @ApiModelProperty(value = "") + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public User lastName(String lastName) { + this.lastName = lastName; + return this; + } + + /** + * Get lastName + * @return lastName + **/ + @ApiModelProperty(value = "") + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public User email(String email) { + this.email = email; + return this; + } + + /** + * Get email + * @return email + **/ + @ApiModelProperty(value = "") + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public User password(String password) { + this.password = password; + return this; + } + + /** + * Get password + * @return password + **/ + @ApiModelProperty(value = "") + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public User phone(String phone) { + this.phone = phone; + return this; + } + + /** + * Get phone + * @return phone + **/ + @ApiModelProperty(value = "") + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public User userStatus(Integer userStatus) { + this.userStatus = userStatus; + return this; + } + + /** + * User Status + * @return userStatus + **/ + @ApiModelProperty(value = "User Status") + public Integer getUserStatus() { + return userStatus; + } + + public void setUserStatus(Integer userStatus) { + this.userStatus = userStatus; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + User user = (User) o; + return Objects.equals(this.id, user.id) && + Objects.equals(this.username, user.username) && + Objects.equals(this.firstName, user.firstName) && + Objects.equals(this.lastName, user.lastName) && + Objects.equals(this.email, user.email) && + Objects.equals(this.password, user.password) && + Objects.equals(this.phone, user.phone) && + Objects.equals(this.userStatus, user.userStatus); + } + + @Override + public int hashCode() { + return Objects.hash(id, username, firstName, lastName, email, password, phone, userStatus); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class User {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" username: ").append(toIndentedString(username)).append("\n"); + sb.append(" firstName: ").append(toIndentedString(firstName)).append("\n"); + sb.append(" lastName: ").append(toIndentedString(lastName)).append("\n"); + sb.append(" email: ").append(toIndentedString(email)).append("\n"); + sb.append(" password: ").append(toIndentedString(password)).append("\n"); + sb.append(" phone: ").append(toIndentedString(phone)).append("\n"); + sb.append(" userStatus: ").append(toIndentedString(userStatus)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/AuthorizationServerConfiguration.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/AuthorizationServerConfiguration.java new file mode 100644 index 00000000000..f2bedfec61c --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/AuthorizationServerConfiguration.java @@ -0,0 +1,61 @@ +package com.prokarma.pkmst.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; +import org.springframework.security.oauth2.provider.token.TokenStore; +/** + * Convenient strategy for configuring an OAUth2 Authorization Server. Beans of this type are applied to the Spring + * context automatically if you {@link EnableAuthorizationServer @EnableAuthorizationServer}. + * + * @author pkmst + * + */ +@Configuration +@EnableAuthorizationServer +public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { + + private static String REALM="MY_OAUTH_REALM"; + + @Autowired + private TokenStore tokenStore; + + @Autowired + private UserApprovalHandler userApprovalHandler; + + @Autowired + @Qualifier("authenticationManagerBean") + private AuthenticationManager authenticationManager; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + + clients.inMemory() + .withClient("my-trusted-client") + .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") + .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") + .scopes("read", "write", "trust") + .secret("secret") + .accessTokenValiditySeconds(120).//Access token is only valid for 2 minutes. + refreshTokenValiditySeconds(600);//Refresh token is only valid for 10 minutes. + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler) + .authenticationManager(authenticationManager); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { + oauthServer.realm(REALM+"/client"); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/OAuth2SecurityConfiguration.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/OAuth2SecurityConfiguration.java new file mode 100644 index 00000000000..ed96778f069 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/OAuth2SecurityConfiguration.java @@ -0,0 +1,82 @@ +package com.prokarma.pkmst.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.SecurityProperties; +import org.springframework.core.annotation.Order; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenApprovalStore; +import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; +/** + * Provides a convenient base class for creating a {@link WebSecurityConfigurer} + * instance. The implementation allows customization by overriding methods. + * + * @see EnableWebSecurity + * + * @author pkmst + */ +@Configuration +@EnableWebSecurity +@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) +public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("admin").password("admin@123").roles("ADMIN").and() + .withUser("user").password("user@123").roles("USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable() + .anonymous().disable() + .authorizeRequests() + .antMatchers("/oauth/token").permitAll(); + } + + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + + @Bean + public TokenStore tokenStore() { + return new InMemoryTokenStore(); + } + + @Bean + @Autowired + public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){ + TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); + handler.setTokenStore(tokenStore); + handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); + handler.setClientDetailsService(clientDetailsService); + return handler; + } + + @Bean + @Autowired + public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception { + TokenApprovalStore store = new TokenApprovalStore(); + store.setTokenStore(tokenStore); + return store; + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/ResourceServerConfiguration.java b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/ResourceServerConfiguration.java new file mode 100644 index 00000000000..a45c1f35647 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/java/com/prokarma/pkmst/security/ResourceServerConfiguration.java @@ -0,0 +1,52 @@ +package com.prokarma.pkmst.security; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.http.HttpMethod; +/** + * Configurer class for @EnableResourceServer classes. This class adjust the access + * rules and paths that are protected by OAuth2 security. If more than one configures the same property, then the last + * one wins. The configurers are sorted by {@link Order} before being applied. + * + * @author pkmst + * + */ +@Configuration +@EnableResourceServer +public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { + + private static final String RESOURCE_ID = "my_rest_api"; + + @Override + public void configure(ResourceServerSecurityConfigurer resources) { + resources.resourceId(RESOURCE_ID).stateless(false); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + //configure security for the http methods + http. + anonymous().disable() + .requestMatchers().antMatchers(HttpMethod.GET, "/pet/**") + .and().authorizeRequests() + .antMatchers(HttpMethod.GET, "/pet/**").access("hasRole('ADMIN')") + .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); + http. + anonymous().disable() + .requestMatchers().antMatchers(HttpMethod.GET, "/store/**") + .and().authorizeRequests() + .antMatchers(HttpMethod.GET, "/store/**").access("hasRole('ADMIN')") + .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); + http. + anonymous().disable() + .requestMatchers().antMatchers(HttpMethod.GET, "/user/**") + .and().authorizeRequests() + .antMatchers(HttpMethod.GET, "/user/**").access("hasRole('ADMIN')") + .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); + } + +} diff --git a/samples/server/petstore/java-pkmst/src/main/resources/application-dev-config.yml b/samples/server/petstore/java-pkmst/src/main/resources/application-dev-config.yml new file mode 100644 index 00000000000..b0fbb498499 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/resources/application-dev-config.yml @@ -0,0 +1,7 @@ +#Enable cloud config. Also enable the dependency in pom + #cloud: + #config: + #uri: + #fail-fast: true + #password: user + #username: user \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/resources/application-dev.yml b/samples/server/petstore/java-pkmst/src/main/resources/application-dev.yml new file mode 100644 index 00000000000..a8218bcc828 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/resources/application-dev.yml @@ -0,0 +1,48 @@ +# Discovery Server Access +server: + port: 8008 + +# Spring Actuator +management: + health: + redis: + enabled: false + security: + enabled: false + + +endpoints: + health: + sensitive: false + +info: + app: + name: Pkmst + description: Microservice developed by PKMST + version: 1.0.0 + +health: + hystrix: + enabled: true + +security: + basic: + enabled: false +# provide rabbitmq configuration +spring: + rabbitmq: + host: + virtual-host: + username: + password: + port: + + sleuth: + sampler: + percentage: 1.0 +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/resources/application-local.yml b/samples/server/petstore/java-pkmst/src/main/resources/application-local.yml new file mode 100644 index 00000000000..cf2af23d832 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/resources/application-local.yml @@ -0,0 +1,49 @@ +# Discovery Server Access +server: + port: 8008 + +# Spring Actuator +management: + health: + redis: + enabled: false + security: + enabled: false + + +endpoints: + health: + sensitive: false + +info: + app: + name: Pkmst + description: Microservice developed by PKMST + version: 1.0.0 + +health: + hystrix: + enabled: true + +security: + basic: + enabled: false +# provide rabbitmq configuration +spring: + rabbitmq: + host: + virtual-host: + username: + password: + port: + + sleuth: + sampler: + percentage: 1.0 +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG + \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/main/resources/bootstrap.yml b/samples/server/petstore/java-pkmst/src/main/resources/bootstrap.yml new file mode 100644 index 00000000000..d353a41ff82 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/main/resources/bootstrap.yml @@ -0,0 +1,5 @@ +spring: + application: + name: pkmst-microservice + profiles: + active: local \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PetApiTest.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PetApiTest.java new file mode 100644 index 00000000000..68e9a0474b8 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PetApiTest.java @@ -0,0 +1,177 @@ +/* + * Swagger Petstore + * This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters. + * + * OpenAPI spec version: 1.0.0 + * Contact: apiteam@swagger.io + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +package com.prokarma.pkmst.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import com.prokarma.pkmst.model.ModelApiResponse; +import com.prokarma.pkmst.model.Pet; +import org.junit.Test; +import org.junit.Ignore; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +/** + * API tests for PetApi + */ +@Ignore +public class PetApiTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final PetApi api = new PetApiController(objectMapper); + + private final String accept = "application/json"; + + + /** + * Add a new pet to the store + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void addPetTest() throws Exception { + Pet body = null; + ResponseEntity response = api.addPet(body , accept); + + // TODO: test validations + } + + /** + * Deletes a pet + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void deletePetTest() throws Exception { + Long petId = null; + String apiKey = null; + ResponseEntity response = api.deletePet(petId, apiKey , accept); + + // TODO: test validations + } + + /** + * Finds Pets by status + * + * Multiple status values can be provided with comma separated strings + * + * @throws Exception + * if the Api call fails + */ + @Test + public void findPetsByStatusTest() throws Exception { + List status = null; + ResponseEntity> response = api.findPetsByStatus(status , accept); + + // TODO: test validations + } + + /** + * Finds Pets by tags + * + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + * + * @throws Exception + * if the Api call fails + */ + @Test + public void findPetsByTagsTest() throws Exception { + List tags = null; + ResponseEntity> response = api.findPetsByTags(tags , accept); + + // TODO: test validations + } + + /** + * Find pet by ID + * + * Returns a single pet + * + * @throws Exception + * if the Api call fails + */ + @Test + public void getPetByIdTest() throws Exception { + Long petId = null; + ResponseEntity response = api.getPetById(petId , accept); + + // TODO: test validations + } + + /** + * Update an existing pet + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void updatePetTest() throws Exception { + Pet body = null; + ResponseEntity response = api.updatePet(body , accept); + + // TODO: test validations + } + + /** + * Updates a pet in the store with form data + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void updatePetWithFormTest() throws Exception { + Long petId = null; + String name = null; + String status = null; + ResponseEntity response = api.updatePetWithForm(petId, name, status , accept); + + // TODO: test validations + } + + /** + * uploads an image + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void uploadFileTest() throws Exception { + Long petId = null; + String additionalMetadata = null; + MultipartFile file = null; + ResponseEntity response = api.uploadFile(petId, additionalMetadata, file , accept); + + // TODO: test validations + } + +} diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PkmstIT.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PkmstIT.java new file mode 100644 index 00000000000..5f4bb3acf74 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/PkmstIT.java @@ -0,0 +1,34 @@ +package com.prokarma.pkmst.controller; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; +import com.prokarma.pkmst.PkmstApplication; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = PkmstApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class PkmstIT { + + @LocalServerPort + private int port; + + TestRestTemplate restTemplate = new TestRestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + + @Test + public void testYourMethod() { + + //add your logic + } + + private String createURLWithPort(String uri) { + return "http://localhost:" + port + uri; + } +} diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/StoreApiTest.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/StoreApiTest.java new file mode 100644 index 00000000000..09acff37e79 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/StoreApiTest.java @@ -0,0 +1,106 @@ +/* + * Swagger Petstore + * This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters. + * + * OpenAPI spec version: 1.0.0 + * Contact: apiteam@swagger.io + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +package com.prokarma.pkmst.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Map; +import com.prokarma.pkmst.model.Order; +import org.junit.Test; +import org.junit.Ignore; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +/** + * API tests for StoreApi + */ +@Ignore +public class StoreApiTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final StoreApi api = new StoreApiController(objectMapper); + + private final String accept = "application/json"; + + + /** + * Delete purchase order by ID + * + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * + * @throws Exception + * if the Api call fails + */ + @Test + public void deleteOrderTest() throws Exception { + String orderId = null; + ResponseEntity response = api.deleteOrder(orderId , accept); + + // TODO: test validations + } + + /** + * Returns pet inventories by status + * + * Returns a map of status codes to quantities + * + * @throws Exception + * if the Api call fails + */ + @Test + public void getInventoryTest() throws Exception { + ResponseEntity> response = api.getInventory( accept); + + // TODO: test validations + } + + /** + * Find purchase order by ID + * + * For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + * + * @throws Exception + * if the Api call fails + */ + @Test + public void getOrderByIdTest() throws Exception { + Long orderId = null; + ResponseEntity response = api.getOrderById(orderId , accept); + + // TODO: test validations + } + + /** + * Place an order for a pet + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void placeOrderTest() throws Exception { + Order body = null; + ResponseEntity response = api.placeOrder(body , accept); + + // TODO: test validations + } + +} diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/UserApiTest.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/UserApiTest.java new file mode 100644 index 00000000000..b0b4e147e51 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/controller/UserApiTest.java @@ -0,0 +1,172 @@ +/* + * Swagger Petstore + * This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters. + * + * OpenAPI spec version: 1.0.0 + * Contact: apiteam@swagger.io + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + +package com.prokarma.pkmst.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import com.prokarma.pkmst.model.User; +import org.junit.Test; +import org.junit.Ignore; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +/** + * API tests for UserApi + */ +@Ignore +public class UserApiTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final UserApi api = new UserApiController(objectMapper); + + private final String accept = "application/json"; + + + /** + * Create user + * + * This can only be done by the logged in user. + * + * @throws Exception + * if the Api call fails + */ + @Test + public void createUserTest() throws Exception { + User body = null; + ResponseEntity response = api.createUser(body , accept); + + // TODO: test validations + } + + /** + * Creates list of users with given input array + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void createUsersWithArrayInputTest() throws Exception { + List body = null; + ResponseEntity response = api.createUsersWithArrayInput(body , accept); + + // TODO: test validations + } + + /** + * Creates list of users with given input array + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void createUsersWithListInputTest() throws Exception { + List body = null; + ResponseEntity response = api.createUsersWithListInput(body , accept); + + // TODO: test validations + } + + /** + * Delete user + * + * This can only be done by the logged in user. + * + * @throws Exception + * if the Api call fails + */ + @Test + public void deleteUserTest() throws Exception { + String username = null; + ResponseEntity response = api.deleteUser(username , accept); + + // TODO: test validations + } + + /** + * Get user by user name + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void getUserByNameTest() throws Exception { + String username = null; + ResponseEntity response = api.getUserByName(username , accept); + + // TODO: test validations + } + + /** + * Logs user into the system + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void loginUserTest() throws Exception { + String username = null; + String password = null; + ResponseEntity response = api.loginUser(username, password , accept); + + // TODO: test validations + } + + /** + * Logs out current logged in user session + * + * + * + * @throws Exception + * if the Api call fails + */ + @Test + public void logoutUserTest() throws Exception { + ResponseEntity response = api.logoutUser( accept); + + // TODO: test validations + } + + /** + * Updated user + * + * This can only be done by the logged in user. + * + * @throws Exception + * if the Api call fails + */ + @Test + public void updateUserTest() throws Exception { + String username = null; + User body = null; + ResponseEntity response = api.updateUser(username, body , accept); + + // TODO: test validations + } + +} diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstSteps.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstSteps.java new file mode 100644 index 00000000000..caf8907693f --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstSteps.java @@ -0,0 +1,76 @@ +package com.prokarma.pkmst.cucumber; +import cucumber.api.java.After; +import cucumber.api.java.Before; +import cucumber.api.java.en.Given; +import cucumber.api.java.en.Then; +import cucumber.api.java.en.When; +import cucumber.api.PendingException; + +public class PkmstSteps { + +@Given("^I want to write a step with precondition$") +public void i_want_to_write_a_step_with_precondition() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Given("^some other precondition$") +public void some_other_precondition() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^I complete action$") +public void i_complete_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^some other action$") +public void some_other_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^yet another action$") +public void yet_another_action() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I validate the outcomes$") +public void i_validate_the_outcomes() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^check more outcomes$") +public void check_more_outcomes() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Given("^I want to write a step with name(\\d+)$") +public void i_want_to_write_a_step_with_name(int arg1) throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@When("^I check for the (\\d+) in step$") +public void i_check_for_the_in_step(int arg1) throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I verify the success in step$") +public void i_verify_the_success_in_step() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} + +@Then("^I verify the Fail in step$") +public void i_verify_the_Fail_in_step() throws Throwable { + // Write code here that turns the phrase above into concrete actions + throw new PendingException(); +} +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstTest.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstTest.java new file mode 100644 index 00000000000..1e8bf880c41 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/PkmstTest.java @@ -0,0 +1,16 @@ +package com.prokarma.pkmst.cucumber; + +import org.junit.runner.RunWith; +import org.springframework.test.context.ActiveProfiles; +import cucumber.api.CucumberOptions; +import cucumber.api.junit.Cucumber; + +@RunWith(Cucumber.class) +@ActiveProfiles("test") +@CucumberOptions(format = { "pretty", "html:target/cucumber-html-report", + "json:./report/pet-report-json/pet.json", + "json:./report/store-report-json/store.json", + "json:./report/user-report-json/user.json", + }) +public class PkmstTest { +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/Pkmstpackage-info.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/Pkmstpackage-info.java new file mode 100644 index 00000000000..81caf63ebbb --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/Pkmstpackage-info.java @@ -0,0 +1,2 @@ +package com.prokarma.pkmst.cucumber; +//Implement the feature file steps in this package. \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/report/ExecuteReport.java b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/report/ExecuteReport.java new file mode 100644 index 00000000000..ed29f822512 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/java/com/prokarma/pkmst/cucumber/report/ExecuteReport.java @@ -0,0 +1,64 @@ +package com.prokarma.pkmst.cucumber.report; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import net.masterthought.cucumber.Configuration; +import net.masterthought.cucumber.ReportBuilder; + +public class ExecuteReport { + + public static void main(String[] args) { + generateReport(); + } + + private static void generateReport() { + String buildNumber = "1"; + String projectName = "Spring-micro-sample"; + boolean runWithJenkins = false; + boolean parallelTesting = false; + + File reportOutputDirectory = null; + List jsonFiles = null; + Configuration configuration = null; + ReportBuilder reportBuilder = null; + reportOutputDirectory = new File("./report/pet-report-html/"); + jsonFiles = new ArrayList(); + jsonFiles.add("./report/pet-report-json/pet.json"); + + configuration = new Configuration(reportOutputDirectory,projectName); + // optionally only if you need + configuration.setParallelTesting(parallelTesting); + configuration.setRunWithJenkins(runWithJenkins); + configuration.setBuildNumber(buildNumber); + + reportBuilder = new ReportBuilder(jsonFiles, configuration); + reportBuilder.generateReports(); + reportOutputDirectory = new File("./report/store-report-html/"); + jsonFiles = new ArrayList(); + jsonFiles.add("./report/store-report-json/store.json"); + + configuration = new Configuration(reportOutputDirectory,projectName); + // optionally only if you need + configuration.setParallelTesting(parallelTesting); + configuration.setRunWithJenkins(runWithJenkins); + configuration.setBuildNumber(buildNumber); + + reportBuilder = new ReportBuilder(jsonFiles, configuration); + reportBuilder.generateReports(); + reportOutputDirectory = new File("./report/user-report-html/"); + jsonFiles = new ArrayList(); + jsonFiles.add("./report/user-report-json/user.json"); + + configuration = new Configuration(reportOutputDirectory,projectName); + // optionally only if you need + configuration.setParallelTesting(parallelTesting); + configuration.setRunWithJenkins(runWithJenkins); + configuration.setBuildNumber(buildNumber); + + reportBuilder = new ReportBuilder(jsonFiles, configuration); + reportBuilder.generateReports(); + + } +} \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/resources/application-test.properties b/samples/server/petstore/java-pkmst/src/test/resources/application-test.properties new file mode 100644 index 00000000000..4ef5c891798 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/application-test.properties @@ -0,0 +1 @@ +server.port = 8081 diff --git a/samples/server/petstore/java-pkmst/src/test/resources/application.conf b/samples/server/petstore/java-pkmst/src/test/resources/application.conf new file mode 100644 index 00000000000..6a42f95f1fa --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/application.conf @@ -0,0 +1,14 @@ +#################################### +# Akka Actor Config File # +#################################### + +akka { + scheduler { + tick-duration = 50ms + } +} + +url="http://localhost:8081" +noOfUsers=10 #Number of Users +deleteProductId=4 #Delete the Product by using productID +getProduct=2 #Get the Product \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/resources/application.properties b/samples/server/petstore/java-pkmst/src/test/resources/application.properties new file mode 100644 index 00000000000..4ef5c891798 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/application.properties @@ -0,0 +1 @@ +server.port = 8081 diff --git a/samples/server/petstore/java-pkmst/src/test/resources/bootstrap.yml b/samples/server/petstore/java-pkmst/src/test/resources/bootstrap.yml new file mode 100644 index 00000000000..4f8e3532104 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/bootstrap.yml @@ -0,0 +1,5 @@ +spring: + application: + name: pkmst-microservice + profiles: + active: test \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/resources/com/prokarma/pkmst/cucumber/Pkmst.feature b/samples/server/petstore/java-pkmst/src/test/resources/com/prokarma/pkmst/cucumber/Pkmst.feature new file mode 100644 index 00000000000..a22095793d4 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/com/prokarma/pkmst/cucumber/Pkmst.feature @@ -0,0 +1,33 @@ +#Feature: List of scenarios. +#Scenario: Business rule through list of steps with arguments. +#Given: Some precondition step +#When: Some key actions +#Then: To observe outcomes or validation +#And,But: To enumerate more Given,When,Then steps +#Scenario Outline: List of steps for data-driven as an Examples and + +#Sample Feature Definition Template +@tag +Feature: Title of your feature + I want to use this template for my feature file + +@tag1 +Scenario: Title of your scenario +Given I want to write a step with precondition + And some other precondition +When I complete action + And some other action + And yet another action +Then I validate the outcomes + And check more outcomes + +@tag2 +Scenario Outline: Title of your scenario outline +Given I want to write a step with +When I check for the in step +Then I verify the in step + +Examples: + | name |value | status | + | name1 | 5 | success| + | name2 | 7 | Fail | \ No newline at end of file diff --git a/samples/server/petstore/java-pkmst/src/test/resources/gatling.conf b/samples/server/petstore/java-pkmst/src/test/resources/gatling.conf new file mode 100644 index 00000000000..c7b4fa7f8c8 --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/resources/gatling.conf @@ -0,0 +1,157 @@ +######################### +# Gatling Configuration # +######################### + +# This file contains all the settings configurable for Gatling with their default values + +gatling { + core { + #outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp) + #runDescription = "" # The description for this simulation run, displayed in each report + #encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation + #simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated) + #mute = false # When set to true, don't ask for simulation name nor run description (currently only used by Gatling SBT plugin) + + extract { + regex { + #cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching + } + xpath { + #cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching + } + jsonPath { + #cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching + #preferJackson = false # When set to true, prefer Jackson over Boon for JSON-related operations + jackson { + #allowComments = false # Allow comments in JSON files + #allowUnquotedFieldNames = false # Allow unquoted JSON fields names + #allowSingleQuotes = false # Allow single quoted JSON field names + } + + } + css { + #cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching + } + } + + timeOut { + #simulation = 8640000 # Absolute timeout, in seconds, of a simulation + } + directory { + #data = src/test/resource/data # Folder where user's data (e.g. files used by Feeders) is located + #bodies = src/test/resource/bodies # Folder where bodies are located + #simulations = user-src/test/java/simulations # Folder where the bundle's simulations are located< + #reportsOnly = "" # If set, name of report folder to look for in order to generate its report + #binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target. + #results = results # Name of the folder where all reports folder are located + } + } + charting { + #noReports = false # When set to true, don't generate HTML reports + #maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports + #accuracy = 10 # Accuracy, in milliseconds, of the report's stats + indicators { + #lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary + #higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary + #percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and GraphiteDataWriter + #percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and GraphiteDataWriter + } + } + http { + #elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable + #rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body Raw templates, set to 0 to disable + #fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable + #fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable + #redirectPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent redirects, set to 0 to disable + #expirePerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent 'Expire' headers, set to 0 to disable + #lastModifiedPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent 'Last-Modified' headers, set to 0 to disable + #etagPerUserCacheMaxCapacity = 200 # Per virtual user cache size for permanent ETag headers, set to 0 to disable + #warmUpUrl = "http://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled) + #enableGA = true # Very light Google Analytics, please support + ssl { + trustStore { + #type = "" # Type of SSLContext's TrustManagers store + #file = "" # Location of SSLContext's TrustManagers store + #password = "" # Password for SSLContext's TrustManagers store + #algorithm = "" # Algorithm used by SSLContext's TrustManagers store + } + keyStore { + #type = "" # Type of SSLContext's KeyManagers store + #file = "" # Location of SSLContext's KeyManagers store + #password = "" # Password for SSLContext's KeyManagers store + #algorithm = "" # Algorithm used SSLContext's KeyManagers store + } + } + ahc { + #allowPoolingConnections = true # Allow pooling HTTP connections (keep-alive header automatically added) + #allowPoolingSslConnections = true # Allow pooling HTTPS connections (keep-alive header automatically added) + #compressionEnforced = false # Enforce gzip/deflate when Accept-Encoding header is not defined + #connectTimeout = 60000 # Timeout when establishing a connection + #pooledConnectionIdleTimeout = 60000 # Timeout when a connection stays unused in the pool + #readTimeout = 60000 # Timeout when a used connection stays idle + #connectionTTL = -1 # Max duration a connection can stay open (-1 means no limit) + #ioThreadMultiplier = 2 # Number of Netty worker threads per core + #maxConnectionsPerHost = -1 # Max number of connections per host (-1 means no limit) + #maxConnections = -1 # Max number of connections (-1 means no limit) + #maxRetry = 2 # Number of times that a request should be tried again + #requestTimeout = 60000 # Timeout of the requests + #useProxyProperties = false # When set to true, supports standard Proxy System properties + #webSocketTimeout = 60000 # Timeout when a used websocket connection stays idle + #useRelativeURIsWithConnectProxies = true # When set to true, use relative URIs when talking with an SSL proxy or a WebSocket proxy + #acceptAnyCertificate = true # When set to true, doesn't validate SSL certificates + #httpClientCodecMaxInitialLineLength = 4096 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK") + #httpClientCodecMaxHeaderSize = 8192 # Maximum size, in bytes, of each request's headers + #httpClientCodecMaxChunkSize = 8192 # Maximum length of the content or each chunk + #keepEncodingHeader = true # Don't drop Encoding response header after decoding + #webSocketMaxFrameSize = 10240 # Maximum frame payload size + #httpsEnabledProtocols = "" # Comma separated enabled protocols for HTTPS, if empty use the JDK defaults + #httpsEnabledCipherSuites = "" # Comma separated enabled cipher suites for HTTPS, if empty use the JDK defaults + #sslSessionCacheSize = 20000 # SSLSession cache size (set to 0 to disable) + #sslSessionTimeout = 86400 # SSLSession timeout (default is 24, like Hotspot) + } + } + data { + #writers = "console, file" # The lists of DataWriters to which Gatling write simulation data (currently supported : "console", "file", "graphite", "jdbc") + #reader = file # The DataReader used by the charting engine for reading simulation results + console { + #light = false # When set to true, displays a light version without detailed request stats + } + file { + #bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes + } + leak { + #noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening + } + jdbc { + db { + #url = "jdbc:mysql://localhost:3306/temp" # The JDBC URL used by the JDBC DataWriter + #username = "root" # The database user used by the JDBC DataWriter + #password = "123123q" # The password for the specified user + } + #bufferSize = 20 # The size for each batch of SQL inserts to send to the database + create { + #createRunRecordTable = "CREATE TABLE IF NOT EXISTS `RunRecords` ( `id` INT NOT NULL AUTO_INCREMENT , `runDate` DATETIME NULL , `simulationId` VARCHAR(45) NULL , `runDescription` VARCHAR(45) NULL , PRIMARY KEY (`id`) )" + #createRequestRecordTable = "CREATE TABLE IF NOT EXISTS `RequestRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenario` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `name` varchar(50) DEFAULT NULL, `requestStartDate` bigint DEFAULT NULL, `requestEndDate` bigint DEFAULT NULL, `responseStartDate` bigint DEFAULT NULL, `responseEndDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, `message` varchar(4500) DEFAULT NULL, `responseTime` bigint DEFAULT NULL, PRIMARY KEY (`id`) )" + #createScenarioRecordTable = "CREATE TABLE IF NOT EXISTS `ScenarioRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `event` varchar(50) DEFAULT NULL, `startDate` bigint DEFAULT NULL, `endDate` bigint DEFAULT NULL, PRIMARY KEY (`id`) )" + #createGroupRecordTable = "CREATE TABLE IF NOT EXISTS `GroupRecords` (`id` int(11) NOT NULL AUTO_INCREMENT, `runId` int DEFAULT NULL, `scenarioName` varchar(45) DEFAULT NULL, `userId` VARCHAR(30) NULL, `entryDate` bigint DEFAULT NULL, `exitDate` bigint DEFAULT NULL, `status` varchar(2) DEFAULT NULL, PRIMARY KEY (`id`) )" + } + insert { + #insertRunRecord = "INSERT INTO RunRecords (runDate, simulationId, runDescription) VALUES (?,?,?)" + #insertRequestRecord = "INSERT INTO RequestRecords (runId, scenario, userId, name, requestStartDate, requestEndDate, responseStartDate, responseEndDate, status, message, responseTime) VALUES (?,?,?,?,?,?,?,?,?,?,?)" + #insertScenarioRecord = "INSERT INTO ScenarioRecords (runId, scenarioName, userId, event, startDate, endDate) VALUES (?,?,?,?,?,?)" + #insertGroupRecord = "INSERT INTO GroupRecords (runId, scenarioName, userId, entryDate, exitDate, status) VALUES (?,?,?,?,?,?)" + } + } + graphite { + #light = false # only send the all* stats + #host = "localhost" # The host where the Carbon server is located + #port = 2003 # The port to which the Carbon server listens to + #protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp") + #rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite + #bufferSize = 8192 # GraphiteDataWriter's internal data buffer size, in bytes + #writeInterval = 1 # GraphiteDataWriter's write interval, in seconds + } + } +} diff --git a/samples/server/petstore/java-pkmst/src/test/scala/scalaFiles/testapi.scala b/samples/server/petstore/java-pkmst/src/test/scala/scalaFiles/testapi.scala new file mode 100644 index 00000000000..11ee5bfda1d --- /dev/null +++ b/samples/server/petstore/java-pkmst/src/test/scala/scalaFiles/testapi.scala @@ -0,0 +1,41 @@ +# Sample gatling test for Get Product. Please implement likewise for your API. +import scala.concurrent.duration._ + +import io.gatling.core.Predef._ +import io.gatling.http.Predef._ +import io.gatling.jdbc.Predef._ +import com.typesafe.config._ +import org.springframework.boot.SpringApplication +import org.springframework.context.ConfigurableApplicationContext + + +class get extends Simulation { + + + val app: ConfigurableApplicationContext = SpringApplication.run(classOf[com.prokarma.pkmst.PkmstApplication]) + Runtime.getRuntime.addShutdownHook(new Thread() { + override def run(): Unit = app.stop() + }) + + val conf = ConfigFactory.load() + val baseUrl = conf.getString("url") + val noOfUsers: Int = conf.getInt("noOfUsers") + val httpProtocol = http + .baseURL(baseUrl) + .inferHtmlResources() + .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") + .acceptEncodingHeader("gzip, deflate, sdch") + .acceptLanguageHeader("en-US,en;q=0.8") + .userAgentHeader("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36") + + val headers_0 = Map( + "Cache-Control" -> "max-age=0", + "Upgrade-Insecure-Requests" -> "1") + + val scn = scenario("getProduct") + .exec(http("request_0") + .get("/") + .headers(headers_0)) + + setUp(scn.inject(atOnceUsers(noOfUsers))).protocols(httpProtocol) +} \ No newline at end of file From 51ef6c1347ce7d85498a2af734b17b2dfeab7ccd Mon Sep 17 00:00:00 2001 From: rkumar-pk Date: Mon, 18 Dec 2017 18:05:34 +0530 Subject: [PATCH 18/19] Added java-pkmst sample to pom.xml.circleci --- pom.xml | 3 +-- pom.xml.circleci | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6c8cf36c2f7..81cb656cfa9 100644 --- a/pom.xml +++ b/pom.xml @@ -838,8 +838,7 @@ - samples/server/petstore/java-pkmst - + samples/client/petstore/php/SwaggerClient-php samples/client/petstore/ruby samples/client/petstore/scala diff --git a/pom.xml.circleci b/pom.xml.circleci index ef26365ef55..38736dbb1c9 100644 --- a/pom.xml.circleci +++ b/pom.xml.circleci @@ -844,6 +844,7 @@ samples/client/petstore/ruby samples/server/petstore/java-inflector + samples/server/petstore/java-pkmst samples/server/petstore/java-play-framework samples/server/petstore/undertow samples/server/petstore/jaxrs/jersey1 From cb26f960bb05a6663c7df9482a666f8793063494 Mon Sep 17 00:00:00 2001 From: sanshuman Date: Mon, 18 Dec 2017 20:12:42 +0530 Subject: [PATCH 19/19] updated readme.mustache --- .../src/main/resources/pkmst/readme.mustache | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache index 0608438c141..38701b4e848 100644 --- a/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache +++ b/modules/swagger-codegen/src/main/resources/pkmst/readme.mustache @@ -142,3 +142,14 @@ http://localhost:8008/swagger-ui.html If all the configurations have been enabled(depending on the port) below are some of the URls to access: eureka: http://localhost:8080 zipkin: http://localhost:9411 + +Please visit below links for more information on PKMST: + +Getting started +https://pkmst-getting-started.mybluemix.net + +Pkmst examples +https://github.com/ProKarma-Inc/pkmst-getting-started-examples + +Pkmst Extensions +https://github.com/ProKarma-Inc/pkmst-extention \ No newline at end of file