diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java new file mode 100644 index 000000000000..3157a258ac7d --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaCodegen.java @@ -0,0 +1,854 @@ +package io.swagger.codegen.languages; + +import com.google.common.base.Strings; +import io.swagger.codegen.*; +import io.swagger.models.Model; +import io.swagger.models.Operation; +import io.swagger.models.Path; +import io.swagger.models.Swagger; +import io.swagger.models.parameters.FormParameter; +import io.swagger.models.parameters.Parameter; +import io.swagger.models.properties.*; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.util.*; +import java.util.regex.Pattern; + + +public abstract class AbstractJavaCodegen extends DefaultCodegen implements CodegenConfig { + + public static final String FULL_JAVA_UTIL = "fullJavaUtil"; + public static final String DEFAULT_LIBRARY = ""; + public static final String DATE_LIBRARY = "dateLibrary"; + + protected String dateLibrary = "joda"; + protected String invokerPackage = "io.swagger"; + protected String groupId = "io.swagger"; + protected String artifactId = "swagger-java"; + protected String artifactVersion = "1.0.0"; + protected String projectFolder = "src" + File.separator + "main"; + protected String projectTestFolder = "src" + File.separator + "test"; + protected String sourceFolder = projectFolder + File.separator + "java"; + protected String testFolder = projectTestFolder + File.separator + "java"; + protected String localVariablePrefix = ""; + protected boolean fullJavaUtil; + protected String javaUtilPrefix = ""; + protected Boolean serializableModel = false; + protected boolean serializeBigDecimalAsString = false; + protected boolean hideGenerationTimestamp = false; + protected String apiDocPath = "docs/"; + protected String modelDocPath = "docs/"; + + public AbstractJavaCodegen() { + super(); + modelTemplateFiles.put("model.mustache", ".java"); + apiTemplateFiles.put("api.mustache", ".java"); + apiTestTemplateFiles.put("api_test.mustache", ".java"); + modelDocTemplateFiles.put("model_doc.mustache", ".md"); + apiDocTemplateFiles.put("api_doc.mustache", ".md"); + + setReservedWordsLowerCase( + Arrays.asList( + // used as internal variables, can collide with parameter names + "localVarPath", "localVarQueryParams", "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") + ); + + languageSpecificPrimitives = new HashSet( + Arrays.asList( + "String", + "boolean", + "Boolean", + "Double", + "Integer", + "Long", + "Float", + "Object", + "byte[]") + ); + instantiationTypes.put("array", "ArrayList"); + instantiationTypes.put("map", "HashMap"); + typeMapping.put("date", "Date"); + typeMapping.put("file", "File"); + typeMapping.put("UUID", "String"); + + cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC)); + cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); + cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC)); + cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, CodegenConstants.GROUP_ID_DESC)); + cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, CodegenConstants.ARTIFACT_ID_DESC)); + cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC)); + cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC)); + cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC)); + cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZABLE_MODEL, CodegenConstants.SERIALIZABLE_MODEL_DESC)); + cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, CodegenConstants + .SERIALIZE_BIG_DECIMAL_AS_STRING_DESC)); + cliOptions.add(CliOption.newBoolean(FULL_JAVA_UTIL, "whether to use fully qualified name for classes under java.util")); + cliOptions.add(new CliOption("hideGenerationTimestamp", "hides the timestamp when files were generated")); + + CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use"); + Map dateOptions = new HashMap(); + dateOptions.put("java8", "Java 8 native"); + dateOptions.put("java8-localdatetime", "Java 8 using LocalDateTime (for legacy app only)"); + dateOptions.put("joda", "Joda"); + dateOptions.put("legacy", "Legacy java.util.Date"); + dateLibrary.setEnum(dateOptions); + + cliOptions.add(dateLibrary); + + } + + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) { + this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE)); + } else { + //not set, use default to be passed to template + additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + } + + if (additionalProperties.containsKey(CodegenConstants.GROUP_ID)) { + this.setGroupId((String) additionalProperties.get(CodegenConstants.GROUP_ID)); + } else { + //not set, use to be passed to template + additionalProperties.put(CodegenConstants.GROUP_ID, groupId); + } + + if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_ID)) { + this.setArtifactId((String) additionalProperties.get(CodegenConstants.ARTIFACT_ID)); + } else { + //not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); + } + + if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) { + this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION)); + } else { + //not set, use to be passed to template + additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); + } + + if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) { + this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER)); + } + + if (additionalProperties.containsKey(CodegenConstants.LOCAL_VARIABLE_PREFIX)) { + this.setLocalVariablePrefix((String) additionalProperties.get(CodegenConstants.LOCAL_VARIABLE_PREFIX)); + } + + if (additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { + this.setSerializableModel(Boolean.valueOf(additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); + } + + if (additionalProperties.containsKey(CodegenConstants.LIBRARY)) { + this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY)); + } + + if(additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { + this.setSerializeBigDecimalAsString(Boolean.valueOf(additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); + } + + // need to put back serializableModel (boolean) into additionalProperties as value in additionalProperties is string + additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); + + if (additionalProperties.containsKey(FULL_JAVA_UTIL)) { + this.setFullJavaUtil(Boolean.valueOf(additionalProperties.get(FULL_JAVA_UTIL).toString())); + } + + if (fullJavaUtil) { + javaUtilPrefix = "java.util."; + } + additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); + additionalProperties.put("javaUtilPrefix", javaUtilPrefix); + + // make api and model doc path available in mustache template + additionalProperties.put("apiDocPath", apiDocPath); + additionalProperties.put("modelDocPath", modelDocPath); + + importMapping.put("List", "java.util.List"); + + if (fullJavaUtil) { + typeMapping.put("array", "java.util.List"); + typeMapping.put("map", "java.util.Map"); + typeMapping.put("DateTime", "java.util.Date"); + typeMapping.remove("List"); + importMapping.remove("Date"); + importMapping.remove("Map"); + importMapping.remove("HashMap"); + importMapping.remove("Array"); + importMapping.remove("ArrayList"); + importMapping.remove("List"); + importMapping.remove("Set"); + importMapping.remove("DateTime"); + instantiationTypes.put("array", "java.util.ArrayList"); + instantiationTypes.put("map", "java.util.HashMap"); + } + + this.sanitizeConfig(); + + // optional jackson mappings for BigDecimal support + importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); + importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); + + // imports for pojos + importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); + importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); + importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); + importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); + importMapping.put("Objects", "java.util.Objects"); + importMapping.put("StringUtil", invokerPackage + ".StringUtil"); + + if(additionalProperties.containsKey(DATE_LIBRARY)) { + setDateLibrary(additionalProperties.get("dateLibrary").toString()); + additionalProperties.put(dateLibrary, "true"); + } + + if("joda".equals(dateLibrary)) { + typeMapping.put("date", "LocalDate"); + typeMapping.put("DateTime", "DateTime"); + + importMapping.put("LocalDate", "org.joda.time.LocalDate"); + importMapping.put("DateTime", "org.joda.time.DateTime"); + } + else if (dateLibrary.startsWith("java8")) { + additionalProperties.put("java8", "true"); + typeMapping.put("date", "LocalDate"); + importMapping.put("LocalDate", "java.time.LocalDate"); + if ("java8-localdatetime".equals(dateLibrary)) { + typeMapping.put("DateTime", "LocalDateTime"); + importMapping.put("LocalDateTime", "java.time.LocalDateTime"); + } else { + typeMapping.put("DateTime", "OffsetDateTime"); + importMapping.put("OffsetDateTime", "java.time.OffsetDateTime"); + } + } + } + + private void sanitizeConfig() { + // Sanitize any config options here. We also have to update the additionalProperties because + // the whole additionalProperties object is injected into the main object passed to the mustache layer + + this.setApiPackage(sanitizePackageName(apiPackage)); + if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) { + this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); + } + + this.setModelPackage(sanitizePackageName(modelPackage)); + if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) { + this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); + } + + this.setInvokerPackage(sanitizePackageName(invokerPackage)); + if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) { + this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); + } + } + + @Override + public String escapeReservedWord(String name) { + return "_" + name; + } + + @Override + public String apiFileFolder() { + return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', '/'); + } + + @Override + public String apiTestFileFolder() { + return outputFolder + "/" + testFolder + "/" + apiPackage().replace('.', '/'); + } + + @Override + public String modelFileFolder() { + return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', '/'); + } + + @Override + public String apiDocFileFolder() { + return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar); + } + + @Override + public String modelDocFileFolder() { + return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar); + } + + @Override + public String toApiDocFilename(String name) { + return toApiName(name); + } + + @Override + public String toModelDocFilename(String name) { + return toModelName(name); + } + + @Override + public String toApiTestFilename(String name) { + return toApiName(name) + "Test"; + } + + @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 ("class".equals(name.toLowerCase())) { + return "PropertyClass"; + } + + if("_".equals(name)) { + name = "_u"; + } + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + // 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) { + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelName(final String name) { + final String sanitizedName = sanitizeName(modelNamePrefix + name + modelNameSuffix); + + // camelize the model name + // phone_number => PhoneNumber + final String camelizedName = camelize(sanitizedName); + + // 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 (name.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 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(); + return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + + 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>()"; + } + 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()"; + } else { + pattern = "new HashMap()"; + } + return String.format(pattern, 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 void setParameterExampleValue(CodegenParameter p) { + String example; + + if (p.defaultValue == null) { + example = p.example; + } else { + example = p.defaultValue; + } + + String type = p.baseType; + if (type == null) { + type = p.dataType; + } + + if ("String".equals(type)) { + if (example == null) { + example = p.paramName + "_example"; + } + example = "\"" + escapeText(example) + "\""; + } else if ("Integer".equals(type) || "Short".equals(type)) { + if (example == null) { + example = "56"; + } + } else if ("Long".equals(type)) { + if (example == null) { + example = "56"; + } + example = example + "L"; + } else if ("Float".equals(type)) { + if (example == null) { + example = "3.4"; + } + example = example + "F"; + } else if ("Double".equals(type)) { + example = "3.4"; + example = example + "D"; + } else if ("Boolean".equals(type)) { + if (example == null) { + example = "true"; + } + } else if ("File".equals(type)) { + if (example == null) { + example = "/path/to/file"; + } + example = "new File(\"" + escapeText(example) + "\")"; + } else if ("Date".equals(type)) { + example = "new Date()"; + } else if (!languageSpecificPrimitives.contains(type)) { + // type is a model class, e.g. User + example = "new " + type + "()"; + } + + if (example == null) { + example = "null"; + } else if (Boolean.TRUE.equals(p.isListContainer)) { + example = "Arrays.asList(" + example + ")"; + } else if (Boolean.TRUE.equals(p.isMapContainer)) { + example = "new HashMap()"; + } + + p.example = example; + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + String type; + if (typeMapping.containsKey(swaggerType)) { + type = typeMapping.get(swaggerType); + if (languageSpecificPrimitives.contains(type) || type.indexOf(".") >= 0 || + type.equals("Map") || type.equals("List") || + type.equals("File") || type.equals("Date")) { + return type; + } + } else { + type = swaggerType; + } + if (null == type) { + LOGGER.error("No Type defined for Property " + p); + } + return toModelName(type); + } + + @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 + 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 (allDefinitions != null && codegenModel != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { + final Model parentModel = allDefinitions.get(codegenModel.parentSchema); + final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); + codegenModel = AbstractJavaCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); + } + + return codegenModel; + } + + @Override + public Map postProcessModelsEnum(Map objs) { + objs = super.postProcessModelsEnum(objs); + String lib = getLibrary(); + if (StringUtils.isEmpty(lib) || "feign".equals(lib) || "jersey2".equals(lib)) { + 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(importMapping.get("JsonValue")); + Map item = new HashMap(); + item.put("import", importMapping.get("JsonValue")); + imports.add(item); + } + } + } + return objs; + } + + @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 ("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"); + // comment out below as it's in the model template + //model.imports.add("Objects"); + + final String lib = getLibrary(); + if(StringUtils.isEmpty(lib) || "feign".equals(lib) || "jersey2".equals(lib)) { + model.imports.add("JsonProperty"); + + if(BooleanUtils.toBoolean(model.hasEnums)) { + model.imports.add("JsonValue"); + } + } + } + return; + } + + @Override + public void postProcessParameter(CodegenParameter parameter) { } + + @Override + public Map postProcessModels(Map objs) { + return postProcessModelsEnum(objs); + } + + @Override + public Map postProcessOperations(Map objs) { + // Remove imports of List, ArrayList, Map and HashMap as they are + // imported in the template already. + List> imports = (List>) objs.get("imports"); + Pattern pattern = Pattern.compile("java\\.util\\.(List|ArrayList|Map|HashMap)"); + for (Iterator> itr = imports.iterator(); itr.hasNext();) { + String _import = itr.next().get("import"); + if (pattern.matcher(_import).matches()) { + itr.remove(); + } + } + return objs; + } + + @Override + public void preprocessSwagger(Swagger swagger) { + if (swagger != null && swagger.getPaths() != null) { + for (String pathname : swagger.getPaths().keySet()) { + Path path = swagger.getPath(pathname); + if (path.getOperations() != null) { + for (Operation operation : path.getOperations()) { + boolean hasFormParameters = false; + for (Parameter parameter : operation.getParameters()) { + if (parameter instanceof FormParameter) { + hasFormParameters = true; + } + } + + String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" : "application/json"; + String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() + ? defaultContentType : operation.getConsumes().get(0); + String accepts = getAccept(operation); + operation.setVendorExtension("x-contentType", contentType); + operation.setVendorExtension("x-accepts", accepts); + } + } + } + } + } + + 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; + } + + @Override + protected boolean needToImport(String type) { + return super.needToImport(type) && type.indexOf(".") < 0; + } +/* + @Override + public String findCommonPrefixOfVars(List vars) { + String prefix = StringUtils.getCommonPrefix(vars.toArray(new String[vars.size()])); + // exclude trailing characters that should be part of a valid variable + // e.g. ["status-on", "status-off"] => "status-" (not "status-o") + return prefix.replaceAll("[a-zA-Z0-9]+\\z", ""); + } +*/ + + @Override + public String toEnumName(CodegenProperty property) { + return sanitizeName(camelize(property.name)) + "Enum"; + } + + @Override + public String toEnumVarName(String value, String datatype) { + // number + if ("Integer".equals(datatype) || "Long".equals(datatype) || + "Float".equals(datatype) || "Double".equals(datatype)) { + String varName = "NUMBER_" + value; + varName = varName.replaceAll("-", "MINUS_"); + varName = varName.replaceAll("\\+", "PLUS_"); + varName = varName.replaceAll("\\.", "_DOT_"); + return varName; + } + + // string + String var = value.replaceAll("\\W+", "_").replaceAll("_+", "_").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) || + "Float".equals(datatype) || "Double".equals(datatype)) { + return value; + } else { + return "\"" + escapeText(value) + "\""; + } + } + + 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) { + + // 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 : null; + } + codegenModel.vars = codegenProperties; + } + } + + return codegenModel; + } + + private static String sanitizePackageName(String packageName) { + packageName = packageName.trim(); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_"); + if(Strings.isNullOrEmpty(packageName)) { + return "invalidPackageName"; + } + return packageName; + } + + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } + + public void setLocalVariablePrefix(String localVariablePrefix) { + this.localVariablePrefix = localVariablePrefix; + } + + public void setSerializeBigDecimalAsString(boolean s) { + this.serializeBigDecimalAsString = s; + } + + public void setSerializableModel(Boolean serializableModel) { + this.serializableModel = serializableModel; + } + + public void setFullJavaUtil(boolean fullJavaUtil) { + this.fullJavaUtil = fullJavaUtil; + } + + public void setDateLibrary(String library) { + this.dateLibrary = library; + } +} diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaJAXRSServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaJAXRSServerCodegen.java index fbb2831ab8b5..d14585142567 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaJAXRSServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractJavaJAXRSServerCodegen.java @@ -1,9 +1,6 @@ package io.swagger.codegen.languages; -import io.swagger.codegen.CodegenOperation; -import io.swagger.codegen.CodegenParameter; -import io.swagger.codegen.CodegenResponse; -import io.swagger.codegen.CodegenType; +import io.swagger.codegen.*; import io.swagger.models.Operation; import io.swagger.models.Path; import io.swagger.models.Swagger; @@ -13,7 +10,7 @@ import org.slf4j.LoggerFactory; import java.util.*; -public abstract class AbstractJavaJAXRSServerCodegen extends JavaClientCodegen { +public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen { /** * Name of the sub-directory in "src/main/resource" where to find the * Mustache template for the JAX-RS Codegen. @@ -26,28 +23,22 @@ public abstract class AbstractJavaJAXRSServerCodegen extends JavaClientCodegen { public AbstractJavaJAXRSServerCodegen() { super(); - dateLibrary = "legacy"; - apiTestTemplateFiles.clear(); // TODO: add test template + + sourceFolder = "src/gen/java"; + invokerPackage = "io.swagger.api"; + artifactId = "swagger-jaxrs-server"; + dateLibrary = "legacy"; //TODO: add joda support to all jax-rs + + apiPackage = "io.swagger.api"; + modelPackage = "io.swagger.model"; + + additionalProperties.put("title", title); + + cliOptions.add(new CliOption(CodegenConstants.IMPL_FOLDER, CodegenConstants.IMPL_FOLDER_DESC)); + cliOptions.add(new CliOption("title", "a title describing the application")); + } - @Override - public void processOpts() { - super.processOpts(); - // clear model and api doc template as AbstractJavaJAXRSServerCodegen - // does not support auto-generated markdown doc at the moment - modelDocTemplateFiles.remove("model_doc.mustache"); - apiDocTemplateFiles.remove("api_doc.mustache"); - } - - // ================ - // ABSTRACT METHODS - // ================ - - @Override - public abstract String getHelp(); - - @Override - public abstract String getName(); // =============== // COMMONS METHODS @@ -59,6 +50,15 @@ public abstract class AbstractJavaJAXRSServerCodegen extends JavaClientCodegen { return CodegenType.SERVER; } + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER)) { + implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER); + } + } + @Override public void preprocessSwagger(Swagger swagger) { if ( "/".equals(swagger.getBasePath()) ) { diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/GroovyClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/GroovyClientCodegen.java index 5b26662531f0..3f9bfbfc6b34 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/GroovyClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/GroovyClientCodegen.java @@ -1,16 +1,13 @@ package io.swagger.codegen.languages; import io.swagger.codegen.*; -import io.swagger.models.Operation; import java.io.File; -import java.util.*; -public class GroovyClientCodegen extends JavaClientCodegen { +public class GroovyClientCodegen extends AbstractJavaCodegen { public static final String CONFIG_PACKAGE = "configPackage"; protected String title = "Petstore Server"; protected String configPackage = ""; - protected String templateFileName = "api.mustache"; public GroovyClientCodegen() { super(); @@ -18,28 +15,28 @@ public class GroovyClientCodegen extends JavaClientCodegen { sourceFolder = projectFolder + File.separator + "groovy"; outputFolder = "generated-code/groovy"; modelTemplateFiles.put("model.mustache", ".groovy"); - apiTemplateFiles.put(templateFileName, ".groovy"); + apiTemplateFiles.put("api.mustache", ".groovy"); apiTestTemplateFiles.clear(); // TODO: add test template embeddedTemplateDir = templateDir = "Groovy"; + + // clear model and api doc template as this codegen + // does not support auto-generated markdown doc at the moment + //TODO: add doc templates + modelDocTemplateFiles.remove("model_doc.mustache"); + apiDocTemplateFiles.remove("api_doc.mustache"); apiPackage = "io.swagger.api"; modelPackage = "io.swagger.model"; configPackage = "io.swagger.configuration"; invokerPackage = "io.swagger.api"; - artifactId = "swagger-spring-mvc-server"; - dateLibrary = "legacy"; + artifactId = "swagger-groovy"; + dateLibrary = "legacy"; //TODO: add joda support to groovy - additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); - additionalProperties.put(CodegenConstants.GROUP_ID, groupId); - additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); - additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); additionalProperties.put("title", title); - additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); additionalProperties.put(CONFIG_PACKAGE, configPackage); cliOptions.add(new CliOption(CONFIG_PACKAGE, "configuration package for generated code")); - supportedLibraries.clear(); } @Override @@ -61,16 +58,10 @@ public class GroovyClientCodegen extends JavaClientCodegen { public void processOpts() { super.processOpts(); - // clear model and api doc template as this codegen - // does not support auto-generated markdown doc at the moment - modelDocTemplateFiles.remove("model_doc.mustache"); - apiDocTemplateFiles.remove("api_doc.mustache"); - if (additionalProperties.containsKey(CONFIG_PACKAGE)) { this.setConfigPackage((String) additionalProperties.get(CONFIG_PACKAGE)); } - supportingFiles.clear(); supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle")); // TODO readme to be added later //supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaCXFServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaCXFServerCodegen.java index 5321e3a59db7..f637a80567c7 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaCXFServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaCXFServerCodegen.java @@ -2,12 +2,9 @@ package io.swagger.codegen.languages; import java.io.File; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import io.swagger.codegen.CliOption; -import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenModel; import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.CodegenProperty; @@ -19,56 +16,26 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen { super(); supportsInheritance = true; - sourceFolder = "src/gen/java"; - invokerPackage = "io.swagger.api"; - artifactId = "swagger-jaxrs-server"; + sourceFolder = "gen" + File.separator + "java"; outputFolder = "generated-code/JavaJaxRS-CXF"; + apiTestTemplateFiles.clear(); // TODO: add test template - modelTemplateFiles.put("model.mustache", ".java"); - apiTemplateFiles.put("api.mustache", ".java"); - apiPackage = "io.swagger.api"; - modelPackage = "io.swagger.model"; + // clear model and api doc template as this codegen + // does not support auto-generated markdown doc at the moment + //TODO: add doc templates + modelDocTemplateFiles.remove("model_doc.mustache"); + apiDocTemplateFiles.remove("api_doc.mustache"); - additionalProperties.put("title", title); typeMapping.put("date", "LocalDate"); typeMapping.put("DateTime", "javax.xml.datatype.XMLGregorianCalendar"); // Map DateTime fields to Java standart class 'XMLGregorianCalendar' importMapping.put("LocalDate", "org.joda.time.LocalDate"); - super.embeddedTemplateDir = templateDir = JAXRS_TEMPLATE_DIRECTORY_NAME + File.separator + "cxf"; + embeddedTemplateDir = templateDir = JAXRS_TEMPLATE_DIRECTORY_NAME + File.separator + "cxf"; - for ( int i = 0; i < cliOptions.size(); i++ ) { - if ( CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt()) ) { - cliOptions.remove(i); - break; - } - } - - CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use"); - library.setDefault(DEFAULT_LIBRARY); - - Map supportedLibraries = new LinkedHashMap(); - - supportedLibraries.put(DEFAULT_LIBRARY, "CXF"); - library.setEnum(supportedLibraries); - - cliOptions.add(library); - cliOptions.add(new CliOption(CodegenConstants.IMPL_FOLDER, CodegenConstants.IMPL_FOLDER_DESC)); - cliOptions.add(new CliOption("title", "a title describing the application")); } - - @Override - public void processOpts() - { - super.processOpts(); - sourceFolder = "gen" + File.separator + "java"; - supportingFiles.clear(); // Don't need extra files provided by AbstractJAX-RS & Java Codegen - - //TODO - //final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/"); - //supportingFiles.add(new SupportingFile("CXF2InterfaceComparator.mustache", invokerFolder, "CXF2InterfaceComparator.java")); - } + @Override public String getName() diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java index 7efdb8c49eb6..f9321f83d264 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java @@ -1,115 +1,35 @@ package io.swagger.codegen.languages; -import com.google.common.base.Strings; import io.swagger.codegen.*; -import io.swagger.models.Model; -import io.swagger.models.Operation; -import io.swagger.models.Path; -import io.swagger.models.Swagger; -import io.swagger.models.parameters.FormParameter; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.*; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; -//import org.apache.commons.lang3.WordUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; -import java.util.regex.Pattern; -public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { +public class JavaClientCodegen extends AbstractJavaCodegen { @SuppressWarnings("hiding") private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class); - public static final String FULL_JAVA_UTIL = "fullJavaUtil"; - public static final String DEFAULT_LIBRARY = ""; - public static final String DATE_LIBRARY = "dateLibrary"; + public static final String USE_RX_JAVA = "useRxJava"; public static final String RETROFIT_1 = "retrofit"; public static final String RETROFIT_2 = "retrofit2"; - protected String dateLibrary = "joda"; - protected String invokerPackage = "io.swagger.client"; - protected String groupId = "io.swagger"; - protected String artifactId = "swagger-java-client"; - protected String artifactVersion = "1.0.0"; - protected String projectFolder = "src" + File.separator + "main"; - protected String projectTestFolder = "src" + File.separator + "test"; - protected String sourceFolder = projectFolder + File.separator + "java"; - protected String testFolder = projectTestFolder + File.separator + "java"; protected String gradleWrapperPackage = "gradle.wrapper"; - protected String localVariablePrefix = ""; - protected boolean fullJavaUtil; - protected String javaUtilPrefix = ""; - protected Boolean serializableModel = false; - protected boolean serializeBigDecimalAsString = false; protected boolean useRxJava = false; - protected boolean hideGenerationTimestamp = false; - protected String apiDocPath = "docs/"; - protected String modelDocPath = "docs/"; public JavaClientCodegen() { super(); outputFolder = "generated-code" + File.separator + "java"; - modelTemplateFiles.put("model.mustache", ".java"); - apiTemplateFiles.put("api.mustache", ".java"); - apiTestTemplateFiles.put("api_test.mustache", ".java"); embeddedTemplateDir = templateDir = "Java"; + invokerPackage = "io.swagger.client"; + artifactId = "swagger-java-client"; apiPackage = "io.swagger.client.api"; modelPackage = "io.swagger.client.model"; - setReservedWordsLowerCase( - Arrays.asList( - // used as internal variables, can collide with parameter names - "localVarPath", "localVarQueryParams", "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") - ); - - languageSpecificPrimitives = new HashSet( - Arrays.asList( - "String", - "boolean", - "Boolean", - "Double", - "Integer", - "Long", - "Float", - "Object", - "byte[]") - ); - instantiationTypes.put("array", "ArrayList"); - instantiationTypes.put("map", "HashMap"); - typeMapping.put("date", "Date"); - typeMapping.put("file", "File"); - typeMapping.put("UUID", "String"); - - cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC)); - cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); - cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC)); - cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, CodegenConstants.GROUP_ID_DESC)); - cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, CodegenConstants.ARTIFACT_ID_DESC)); - cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC)); - cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC)); - cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC)); - cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZABLE_MODEL, CodegenConstants.SERIALIZABLE_MODEL_DESC)); - cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, CodegenConstants - .SERIALIZE_BIG_DECIMAL_AS_STRING_DESC)); - cliOptions.add(CliOption.newBoolean(FULL_JAVA_UTIL, "whether to use fully qualified name for classes under java.util")); cliOptions.add(CliOption.newBoolean(USE_RX_JAVA, "Whether to use the RxJava adapter with the retrofit2 library.")); - cliOptions.add(new CliOption("hideGenerationTimestamp", "hides the timestamp when files were generated")); supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.19.1. JSON processing: Jackson 2.7.0"); supportedLibraries.put("feign", "HTTP client: Netflix Feign 8.16.0. JSON processing: Jackson 2.7.0"); @@ -124,15 +44,6 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { library.setDefault(DEFAULT_LIBRARY); cliOptions.add(library); - CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use"); - Map dateOptions = new HashMap(); - dateOptions.put("java8", "Java 8 native"); - dateOptions.put("java8-localdatetime", "Java 8 using LocalDateTime (for legacy app only)"); - dateOptions.put("joda", "Joda"); - dateOptions.put("legacy", "Legacy java.util.Date"); - dateLibrary.setEnum(dateOptions); - - cliOptions.add(dateLibrary); } @Override @@ -154,109 +65,14 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { public void processOpts() { super.processOpts(); - if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) { - this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE)); - } else { - //not set, use default to be passed to template - additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); - } - - if (additionalProperties.containsKey(CodegenConstants.GROUP_ID)) { - this.setGroupId((String) additionalProperties.get(CodegenConstants.GROUP_ID)); - } else { - //not set, use to be passed to template - additionalProperties.put(CodegenConstants.GROUP_ID, groupId); - } - - if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_ID)) { - this.setArtifactId((String) additionalProperties.get(CodegenConstants.ARTIFACT_ID)); - } else { - //not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); - } - - if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) { - this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION)); - } else { - //not set, use to be passed to template - additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); - } - - if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) { - this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER)); - } - - if (additionalProperties.containsKey(CodegenConstants.LOCAL_VARIABLE_PREFIX)) { - this.setLocalVariablePrefix((String) additionalProperties.get(CodegenConstants.LOCAL_VARIABLE_PREFIX)); - } - - if (additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) { - this.setSerializableModel(Boolean.valueOf(additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL).toString())); - } - - if (additionalProperties.containsKey(CodegenConstants.LIBRARY)) { - this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY)); - } - - if(additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) { - this.setSerializeBigDecimalAsString(Boolean.valueOf(additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString())); - } - - // need to put back serializableModel (boolean) into additionalProperties as value in additionalProperties is string - additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); - - if (additionalProperties.containsKey(FULL_JAVA_UTIL)) { - this.setFullJavaUtil(Boolean.valueOf(additionalProperties.get(FULL_JAVA_UTIL).toString())); - } - if (additionalProperties.containsKey(USE_RX_JAVA)) { this.setUseRxJava(Boolean.valueOf(additionalProperties.get(USE_RX_JAVA).toString())); } - if (fullJavaUtil) { - javaUtilPrefix = "java.util."; - } - additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); - additionalProperties.put("javaUtilPrefix", javaUtilPrefix); - - // make api and model doc path available in mustache template - additionalProperties.put("apiDocPath", apiDocPath); - additionalProperties.put("modelDocPath", modelDocPath); - - importMapping.put("List", "java.util.List"); - - if (fullJavaUtil) { - typeMapping.put("array", "java.util.List"); - typeMapping.put("map", "java.util.Map"); - typeMapping.put("DateTime", "java.util.Date"); - typeMapping.remove("List"); - importMapping.remove("Date"); - importMapping.remove("Map"); - importMapping.remove("HashMap"); - importMapping.remove("Array"); - importMapping.remove("ArrayList"); - importMapping.remove("List"); - importMapping.remove("Set"); - importMapping.remove("DateTime"); - instantiationTypes.put("array", "java.util.ArrayList"); - instantiationTypes.put("map", "java.util.HashMap"); - } - - this.sanitizeConfig(); - - - // optional jackson mappings for BigDecimal support - importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer"); - importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize"); - - // imports for pojos - importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); - importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); - importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); - importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); - importMapping.put("Objects", "java.util.Objects"); - importMapping.put("StringUtil", invokerPackage + ".StringUtil"); final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/"); + final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/"); + + //Common files writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml")); writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md")); writeOptional(outputFolder, new SupportingFile("build.gradle.mustache", "", "build.gradle")); @@ -266,25 +82,24 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml")); supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java")); supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java")); - - final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/"); - if ("feign".equals(getLibrary())) { - supportingFiles.add(new SupportingFile("FormAwareEncoder.mustache", invokerFolder, "FormAwareEncoder.java")); - - //gradleWrapper files - supportingFiles.add( new SupportingFile( "gradlew.mustache", "", "gradlew") ); - supportingFiles.add( new SupportingFile( "gradlew.bat.mustache", "", "gradlew.bat") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.properties.mustache", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.properties") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.jar", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.jar") ); - // "build.sbt" is for development with SBT - supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt")); - } supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java")); supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java")); supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java")); supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java")); + supportingFiles.add( new SupportingFile( "gradlew.mustache", "", "gradlew") ); + supportingFiles.add( new SupportingFile( "gradlew.bat.mustache", "", "gradlew.bat") ); + supportingFiles.add( new SupportingFile( "gradle-wrapper.properties.mustache", + gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.properties") ); + supportingFiles.add( new SupportingFile( "gradle-wrapper.jar", + gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.jar") ); + supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh")); + supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore")); + + //TODO: add doc to retrofit1 and feign + if ( "feign".equals(getLibrary()) || "retrofit".equals(getLibrary()) ){ + modelDocTemplateFiles.remove("model_doc.mustache"); + apiDocTemplateFiles.remove("api_doc.mustache"); + } if (!("feign".equals(getLibrary()) || usesAnyRetrofitLibrary())) { supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java")); @@ -294,103 +109,25 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { } // library-specific files - if (StringUtils.isEmpty(getLibrary())) { - // generate markdown docs - modelDocTemplateFiles.put("model_doc.mustache", ".md"); - apiDocTemplateFiles.put("api_doc.mustache", ".md"); + if (!StringUtils.isEmpty(getLibrary())) { + //TODO: add sbt support to default client + supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt")); - //gradleWrapper files - supportingFiles.add( new SupportingFile( "gradlew.mustache", "", "gradlew") ); - supportingFiles.add( new SupportingFile( "gradlew.bat.mustache", "", "gradlew.bat") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.properties.mustache", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.properties") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.jar", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.jar") ); + } else if ("feign".equals(getLibrary())) { + supportingFiles.add(new SupportingFile("FormAwareEncoder.mustache", invokerFolder, "FormAwareEncoder.java")); } else if ("okhttp-gson".equals(getLibrary())) { - // generate markdown docs - modelDocTemplateFiles.put("model_doc.mustache", ".md"); - apiDocTemplateFiles.put("api_doc.mustache", ".md"); // the "okhttp-gson" library template requires "ApiCallback.mustache" for async call supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java")); supportingFiles.add(new SupportingFile("ApiResponse.mustache", invokerFolder, "ApiResponse.java")); supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java")); supportingFiles.add(new SupportingFile("ProgressRequestBody.mustache", invokerFolder, "ProgressRequestBody.java")); supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java")); - // "build.sbt" is for development with SBT - supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt")); - - //gradleWrapper files - supportingFiles.add( new SupportingFile( "gradlew.mustache", "", "gradlew") ); - supportingFiles.add( new SupportingFile( "gradlew.bat.mustache", "", "gradlew.bat") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.properties.mustache", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.properties") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.jar", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.jar") ); } else if (usesAnyRetrofitLibrary()) { supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java")); supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java")); - - //gradleWrapper files - supportingFiles.add( new SupportingFile( "gradlew.mustache", "", "gradlew") ); - supportingFiles.add( new SupportingFile( "gradlew.bat.mustache", "", "gradlew.bat") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.properties.mustache", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.properties") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.jar", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.jar") ); - // "build.sbt" is for development with SBT - supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt")); - - //generate markdown docs for retrofit2 - if ( usesRetrofit2Library() ){ - modelDocTemplateFiles.put("model_doc.mustache", ".md"); - apiDocTemplateFiles.put("api_doc.mustache", ".md"); - } - } else if("jersey2".equals(getLibrary())) { - // generate markdown docs - modelDocTemplateFiles.put("model_doc.mustache", ".md"); - apiDocTemplateFiles.put("api_doc.mustache", ".md"); supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java")); - - //gradleWrapper files - supportingFiles.add( new SupportingFile( "gradlew.mustache", "", "gradlew") ); - supportingFiles.add( new SupportingFile( "gradlew.bat.mustache", "", "gradlew.bat") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.properties.mustache", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.properties") ); - supportingFiles.add( new SupportingFile( "gradle-wrapper.jar", - gradleWrapperPackage.replace( ".", File.separator ), "gradle-wrapper.jar") ); - // "build.sbt" is for development with SBT - supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt")); } - - if(additionalProperties.containsKey(DATE_LIBRARY)) { - setDateLibrary(additionalProperties.get(DATE_LIBRARY).toString()); - additionalProperties.put(dateLibrary, "true"); - } - - if("joda".equals(dateLibrary)) { - typeMapping.put("date", "LocalDate"); - typeMapping.put("DateTime", "DateTime"); - - importMapping.put("LocalDate", "org.joda.time.LocalDate"); - importMapping.put("DateTime", "org.joda.time.DateTime"); - } - else if (dateLibrary.startsWith("java8")) { - additionalProperties.put("java8", "true"); - typeMapping.put("date", "LocalDate"); - importMapping.put("LocalDate", "java.time.LocalDate"); - if ("java8-localdatetime".equals(dateLibrary)) { - typeMapping.put("DateTime", "LocalDateTime"); - importMapping.put("LocalDateTime", "java.time.LocalDateTime"); - } else { - typeMapping.put("DateTime", "OffsetDateTime"); - importMapping.put("OffsetDateTime", "java.time.OffsetDateTime"); - } - } - - supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh")); - supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore")); - } private boolean usesAnyRetrofitLibrary() { @@ -401,420 +138,9 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { return getLibrary() != null && getLibrary().contains(RETROFIT_2); } - private void sanitizeConfig() { - // Sanitize any config options here. We also have to update the additionalProperties because - // the whole additionalProperties object is injected into the main object passed to the mustache layer - - this.setApiPackage(sanitizePackageName(apiPackage)); - if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) { - this.additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); - } - - this.setModelPackage(sanitizePackageName(modelPackage)); - if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) { - this.additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); - } - - this.setInvokerPackage(sanitizePackageName(invokerPackage)); - if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) { - this.additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); - } - } - - @Override - public String escapeReservedWord(String name) { - return "_" + name; - } - - @Override - public String apiFileFolder() { - return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', '/'); - } - - @Override - public String apiTestFileFolder() { - return outputFolder + "/" + testFolder + "/" + apiPackage().replace('.', '/'); - } - - @Override - public String modelFileFolder() { - return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', '/'); - } - - @Override - public String apiDocFileFolder() { - return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar); - } - - @Override - public String modelDocFileFolder() { - return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar); - } - - @Override - public String toApiDocFilename(String name) { - return toApiName(name); - } - - @Override - public String toModelDocFilename(String name) { - return toModelName(name); - } - - @Override - public String toApiTestFilename(String name) { - return toApiName(name) + "Test"; - } - - @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 ("class".equals(name.toLowerCase())) { - return "PropertyClass"; - } - - if("_".equals(name)) { - name = "_u"; - } - - // if it's all uppper case, do nothing - if (name.matches("^[A-Z_]*$")) { - return name; - } - - // 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) { - // should be the same as variable name - return toVarName(name); - } - - @Override - public String toModelName(final String name) { - final String sanitizedName = sanitizeName(modelNamePrefix + name + modelNameSuffix); - - // camelize the model name - // phone_number => PhoneNumber - final String camelizedName = camelize(sanitizedName); - - // 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 (name.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 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(); - return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; - } else if (p instanceof MapProperty) { - MapProperty mp = (MapProperty) p; - Property inner = mp.getAdditionalProperties(); - - 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>()"; - } - 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()"; - } else { - pattern = "new HashMap()"; - } - return String.format(pattern, 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 void setParameterExampleValue(CodegenParameter p) { - String example; - - if (p.defaultValue == null) { - example = p.example; - } else { - example = p.defaultValue; - } - - String type = p.baseType; - if (type == null) { - type = p.dataType; - } - - if ("String".equals(type)) { - if (example == null) { - example = p.paramName + "_example"; - } - example = "\"" + escapeText(example) + "\""; - } else if ("Integer".equals(type) || "Short".equals(type)) { - if (example == null) { - example = "56"; - } - } else if ("Long".equals(type)) { - if (example == null) { - example = "56"; - } - example = example + "L"; - } else if ("Float".equals(type)) { - if (example == null) { - example = "3.4"; - } - example = example + "F"; - } else if ("Double".equals(type)) { - example = "3.4"; - example = example + "D"; - } else if ("Boolean".equals(type)) { - if (example == null) { - example = "true"; - } - } else if ("File".equals(type)) { - if (example == null) { - example = "/path/to/file"; - } - example = "new File(\"" + escapeText(example) + "\")"; - } else if ("Date".equals(type)) { - example = "new Date()"; - } else if (!languageSpecificPrimitives.contains(type)) { - // type is a model class, e.g. User - example = "new " + type + "()"; - } - - if (example == null) { - example = "null"; - } else if (Boolean.TRUE.equals(p.isListContainer)) { - example = "Arrays.asList(" + example + ")"; - } else if (Boolean.TRUE.equals(p.isMapContainer)) { - example = "new HashMap()"; - } - - p.example = example; - } - - @Override - public String getSwaggerType(Property p) { - String swaggerType = super.getSwaggerType(p); - String type = null; - if (typeMapping.containsKey(swaggerType)) { - type = typeMapping.get(swaggerType); - if (languageSpecificPrimitives.contains(type) || type.indexOf(".") >= 0 || - type.equals("Map") || type.equals("List") || - type.equals("File") || type.equals("Date")) { - return type; - } - } else { - type = swaggerType; - } - if (null == type) { - LOGGER.error("No Type defined for Property " + p); - } - return toModelName(type); - } - - @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 - 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 (allDefinitions != null && codegenModel != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { - final Model parentModel = allDefinitions.get(codegenModel.parentSchema); - final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); - codegenModel = JavaClientCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); - } - - return codegenModel; - } - - @Override - public Map postProcessModelsEnum(Map objs) { - objs = super.postProcessModelsEnum(objs); - String lib = getLibrary(); - if (StringUtils.isEmpty(lib) || "feign".equals(lib) || "jersey2".equals(lib)) { - 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(importMapping.get("JsonValue")); - Map item = new HashMap(); - item.put("import", importMapping.get("JsonValue")); - imports.add(item); - } - } - } - return objs; - } - - @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 ("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"); - // comment out below as it's in the model template - //model.imports.add("Objects"); - - final String lib = getLibrary(); - if(StringUtils.isEmpty(lib) || "feign".equals(lib) || "jersey2".equals(lib)) { - model.imports.add("JsonProperty"); - - if(BooleanUtils.toBoolean(model.hasEnums)) { - model.imports.add("JsonValue"); - } - } - } - return; - } - - @Override - public void postProcessParameter(CodegenParameter parameter) { - return; - } - - @Override - public Map postProcessModels(Map objs) { - return postProcessModelsEnum(objs); - } - @Override public Map postProcessOperations(Map objs) { - // Remove imports of List, ArrayList, Map and HashMap as they are - // imported in the template already. - List> imports = (List>) objs.get("imports"); - Pattern pattern = Pattern.compile("java\\.util\\.(List|ArrayList|Map|HashMap)"); - for (Iterator> itr = imports.iterator(); itr.hasNext();) { - String _import = itr.next().get("import"); - if (pattern.matcher(_import).matches()) { - itr.remove(); - } - } - + super.postProcessOperations(objs); if(usesAnyRetrofitLibrary()) { Map operations = (Map) objs.get("operations"); if (operations != null) { @@ -839,208 +165,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { return objs; } - @Override - public void preprocessSwagger(Swagger swagger) { - if (swagger != null && swagger.getPaths() != null) { - for (String pathname : swagger.getPaths().keySet()) { - Path path = swagger.getPath(pathname); - if (path.getOperations() != null) { - for (Operation operation : path.getOperations()) { - boolean hasFormParameters = false; - for (Parameter parameter : operation.getParameters()) { - if (parameter instanceof FormParameter) { - hasFormParameters = true; - } - } - - String defaultContentType = hasFormParameters ? "application/x-www-form-urlencoded" : "application/json"; - String contentType = operation.getConsumes() == null || operation.getConsumes().isEmpty() - ? defaultContentType : operation.getConsumes().get(0); - String accepts = getAccept(operation); - operation.setVendorExtension("x-contentType", contentType); - operation.setVendorExtension("x-accepts", accepts); - } - } - } - } - } - - 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; - } - - @Override - protected boolean needToImport(String type) { - return super.needToImport(type) && type.indexOf(".") < 0; - } -/* - @Override - public String findCommonPrefixOfVars(List vars) { - String prefix = StringUtils.getCommonPrefix(vars.toArray(new String[vars.size()])); - // exclude trailing characters that should be part of a valid variable - // e.g. ["status-on", "status-off"] => "status-" (not "status-o") - return prefix.replaceAll("[a-zA-Z0-9]+\\z", ""); - } -*/ - - @Override - public String toEnumName(CodegenProperty property) { - return sanitizeName(camelize(property.name)) + "Enum"; - } - - @Override - public String toEnumVarName(String value, String datatype) { - // number - if ("Integer".equals(datatype) || "Long".equals(datatype) || - "Float".equals(datatype) || "Double".equals(datatype)) { - String varName = "NUMBER_" + value; - varName = varName.replaceAll("-", "MINUS_"); - varName = varName.replaceAll("\\+", "PLUS_"); - varName = varName.replaceAll("\\.", "_DOT_"); - return varName; - } - - // string - String var = value.replaceAll("\\W+", "_").replaceAll("_+", "_").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) || - "Float".equals(datatype) || "Double".equals(datatype)) { - return value; - } else { - return "\"" + escapeText(value) + "\""; - } - } - - 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) { - - // 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 : null; - } - codegenModel.vars = codegenProperties; - } - } - - return codegenModel; - } - - public void setInvokerPackage(String invokerPackage) { - this.invokerPackage = invokerPackage; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public void setArtifactId(String artifactId) { - this.artifactId = artifactId; - } - - public void setArtifactVersion(String artifactVersion) { - this.artifactVersion = artifactVersion; - } - - public void setSourceFolder(String sourceFolder) { - this.sourceFolder = sourceFolder; - } - - public void setLocalVariablePrefix(String localVariablePrefix) { - this.localVariablePrefix = localVariablePrefix; - } - - public void setSerializeBigDecimalAsString(boolean s) { - this.serializeBigDecimalAsString = s; - } - - public Boolean getSerializableModel() { - return serializableModel; - } - - public void setSerializableModel(Boolean serializableModel) { - this.serializableModel = serializableModel; - } - - private static String sanitizePackageName(String packageName) { - packageName = packageName.trim(); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. - packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_"); - if(Strings.isNullOrEmpty(packageName)) { - return "invalidPackageName"; - } - return packageName; - } - - public void setFullJavaUtil(boolean fullJavaUtil) { - this.fullJavaUtil = fullJavaUtil; - } - public void setUseRxJava(boolean useRxJava) { this.useRxJava = useRxJava; } - - public void setDateLibrary(String library) { this.dateLibrary = library; } } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaInflectorServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaInflectorServerCodegen.java index 8a08bf758a3f..f586a11baf0a 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaInflectorServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaInflectorServerCodegen.java @@ -4,16 +4,13 @@ import com.fasterxml.jackson.core.JsonProcessingException; import io.swagger.codegen.*; import io.swagger.models.Operation; import io.swagger.models.Swagger; -import io.swagger.models.properties.ArrayProperty; -import io.swagger.models.properties.MapProperty; -import io.swagger.models.properties.Property; import io.swagger.util.Yaml; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; -public class JavaInflectorServerCodegen extends JavaClientCodegen { +public class JavaInflectorServerCodegen extends AbstractJavaCodegen { private static final Logger LOGGER = LoggerFactory.getLogger(JavaInflectorServerCodegen.class); @@ -23,34 +20,23 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen { super(); sourceFolder = "src/gen/java"; - modelTemplateFiles.put("model.mustache", ".java"); - apiTemplateFiles.put("api.mustache", ".java"); apiTestTemplateFiles.clear(); // TODO: add test template embeddedTemplateDir = templateDir = "JavaInflector"; invokerPackage = "io.swagger.handler"; artifactId = "swagger-inflector-server"; - dateLibrary = "legacy"; + dateLibrary = "legacy"; //TODO: add joda support + + // clear model and api doc template as this codegen + // does not support auto-generated markdown doc at the moment + //TODO: add doc templates + modelDocTemplateFiles.remove("model_doc.mustache"); + apiDocTemplateFiles.remove("api_doc.mustache"); + apiPackage = System.getProperty("swagger.codegen.inflector.apipackage", "io.swagger.handler"); modelPackage = System.getProperty("swagger.codegen.inflector.modelpackage", "io.swagger.model"); - additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); - additionalProperties.put(CodegenConstants.GROUP_ID, groupId); - additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); - additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); additionalProperties.put("title", title); - - languageSpecificPrimitives = new HashSet( - Arrays.asList( - "byte[]", - "String", - "boolean", - "Boolean", - "Double", - "Integer", - "Long", - "Float") - ); } @Override @@ -72,12 +58,6 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen { public void processOpts() { super.processOpts(); - // clear model and api doc template as this codegen - // does not support auto-generated markdown doc at the moment - modelDocTemplateFiles.remove("model_doc.mustache"); - apiDocTemplateFiles.remove("api_doc.mustache"); - - supportingFiles.clear(); writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml")); writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md")); writeOptional(outputFolder, new SupportingFile("web.mustache", "src/main/webapp/WEB-INF", "web.xml")); diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaJerseyServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaJerseyServerCodegen.java index f6c3f861e492..f543b29903b3 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaJerseyServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaJerseyServerCodegen.java @@ -3,7 +3,6 @@ package io.swagger.codegen.languages; import io.swagger.codegen.*; import io.swagger.models.Operation; -import java.io.File; import java.util.*; import org.apache.commons.lang3.StringUtils; @@ -12,31 +11,21 @@ public class JavaJerseyServerCodegen extends AbstractJavaJAXRSServerCodegen { public JavaJerseyServerCodegen() { super(); - sourceFolder = "src/gen/java"; - invokerPackage = "io.swagger.api"; - artifactId = "swagger-jaxrs-server"; outputFolder = "generated-code/JavaJaxRS-Jersey"; - modelTemplateFiles.put("model.mustache", ".java"); - apiTemplateFiles.put("api.mustache", ".java"); apiTemplateFiles.put("apiService.mustache", ".java"); apiTemplateFiles.put("apiServiceImpl.mustache", ".java"); apiTemplateFiles.put("apiServiceFactory.mustache", ".java"); + apiTestTemplateFiles.clear(); // TODO: add test template - apiPackage = "io.swagger.api"; - modelPackage = "io.swagger.model"; - - additionalProperties.put("title", title); + // clear model and api doc template as this codegen + // does not support auto-generated markdown doc at the moment + //TODO: add doc templates + modelDocTemplateFiles.remove("model_doc.mustache"); + apiDocTemplateFiles.remove("api_doc.mustache"); embeddedTemplateDir = templateDir = JAXRS_TEMPLATE_DIRECTORY_NAME; - for ( int i = 0; i < cliOptions.size(); i++ ) { - if ( CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt()) ) { - cliOptions.remove(i); - break; - } - } - CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use"); supportedLibraries.put("jersey1", "Jersey core 1.x"); @@ -45,8 +34,7 @@ public class JavaJerseyServerCodegen extends AbstractJavaJAXRSServerCodegen { library.setDefault("jersey1"); cliOptions.add(library); - cliOptions.add(new CliOption(CodegenConstants.IMPL_FOLDER, CodegenConstants.IMPL_FOLDER_DESC)); - cliOptions.add(new CliOption("title", "a title describing the application")); + } @Override @@ -78,13 +66,6 @@ public class JavaJerseyServerCodegen extends AbstractJavaJAXRSServerCodegen { setLibrary("jersey2"); } - supportingFiles.clear(); - - // clear model and api doc template as this codegen - // does not support auto-generated markdown doc at the moment - modelDocTemplateFiles.remove("model_doc.mustache"); - apiDocTemplateFiles.remove("api_doc.mustache"); - if ( additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER)) { implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER); } @@ -137,7 +118,4 @@ public class JavaJerseyServerCodegen extends AbstractJavaJAXRSServerCodegen { co.baseName = basePath; } - public void hideGenerationTimestamp(boolean hideGenerationTimestamp) { - this.hideGenerationTimestamp = hideGenerationTimestamp; - } } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaResteasyServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaResteasyServerCodegen.java index 33803b087b86..d77a4f32067e 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaResteasyServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaResteasyServerCodegen.java @@ -2,66 +2,34 @@ package io.swagger.codegen.languages; import io.swagger.codegen.*; import io.swagger.models.Operation; -import io.swagger.models.Path; -import io.swagger.models.Swagger; import org.apache.commons.lang3.StringUtils; import java.io.File; import java.util.*; -public class JavaResteasyServerCodegen extends JavaClientCodegen implements CodegenConfig { - - protected String dateLibrary = "default"; - protected String title = "Swagger Server"; - protected String implFolder = "src/main/java"; - - public static final String DATE_LIBRARY = "dateLibrary"; +public class JavaResteasyServerCodegen extends AbstractJavaJAXRSServerCodegen { public JavaResteasyServerCodegen() { super(); - sourceFolder = "src/gen/java"; - invokerPackage = "io.swagger.api"; artifactId = "swagger-jaxrs-resteasy-server"; outputFolder = "generated-code/javaJaxRS"; - modelTemplateFiles.put("model.mustache", ".java"); - apiTemplateFiles.put("api.mustache", ".java"); apiTemplateFiles.put("apiService.mustache", ".java"); apiTemplateFiles.put("apiServiceImpl.mustache", ".java"); apiTemplateFiles.put("apiServiceFactory.mustache", ".java"); apiTestTemplateFiles.clear(); // TODO: add test template - apiPackage = "io.swagger.api"; - modelPackage = "io.swagger.model"; - dateLibrary = "legacy"; - additionalProperties.put("title", title); + // clear model and api doc template as AbstractJavaJAXRSServerCodegen + // does not support auto-generated markdown doc at the moment + //TODO: add doc templates + modelDocTemplateFiles.remove("model_doc.mustache"); + apiDocTemplateFiles.remove("api_doc.mustache"); + + dateLibrary = "legacy";// TODO: change to joda embeddedTemplateDir = templateDir = "JavaJaxRS" + File.separator + "resteasy"; - - for (int i = 0; i < cliOptions.size(); i++) { - if (CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt())) { - cliOptions.remove(i); - break; - } - } - - CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use"); - library.setDefault(DEFAULT_LIBRARY); - - Map supportedLibraries = new LinkedHashMap(); - - supportedLibraries.put(DEFAULT_LIBRARY, "Resteasy core 3.0.11"); - library.setEnum(supportedLibraries); - - cliOptions.add(library); - cliOptions.add(new CliOption(CodegenConstants.IMPL_FOLDER, CodegenConstants.IMPL_FOLDER_DESC)); - } - - @Override - public CodegenType getTag() { - return CodegenType.SERVER; } @Override @@ -78,16 +46,6 @@ public class JavaResteasyServerCodegen extends JavaClientCodegen implements Code public void processOpts() { super.processOpts(); - // clear model and api doc template as AbstractJavaJAXRSServerCodegen - // does not support auto-generated markdown doc at the moment - modelDocTemplateFiles.remove("model_doc.mustache"); - apiDocTemplateFiles.remove("api_doc.mustache"); - - if (additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER)) { - implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER); - } - - supportingFiles.clear(); writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml")); writeOptional(outputFolder, new SupportingFile("gradle.mustache", "", "build.gradle")); writeOptional(outputFolder, new SupportingFile("settingsGradle.mustache", "", "settings.gradle")); @@ -152,51 +110,6 @@ public class JavaResteasyServerCodegen extends JavaClientCodegen implements Code co.baseName = basePath; } - - @Override - public void preprocessSwagger(Swagger swagger) { - if ("/".equals(swagger.getBasePath())) { - swagger.setBasePath(""); - } - - String host = swagger.getHost(); - String port = "8080"; - if (host != null) { - String[] parts = host.split(":"); - if (parts.length > 1) { - port = parts[1]; - } - } - this.additionalProperties.put("serverPort", port); - if (swagger != null && 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 Map postProcessOperations(Map objs) { @@ -249,53 +162,6 @@ public class JavaResteasyServerCodegen extends JavaClientCodegen implements Code return objs; } - @Override - public String toApiName(String name) { - if (name.length() == 0) { - return "DefaultApi"; - } - name = sanitizeName(name); - return camelize(name) + "Api"; - } - - - @Override - public String apiFilename(String templateName, String tag) { - - String result = super.apiFilename(templateName, tag); - - if (templateName.endsWith("Impl.mustache")) { - int ix = result.lastIndexOf('/'); - result = result.substring(0, ix) + "/impl" + result.substring(ix, result.length() - 5) + "ServiceImpl.java"; - - result = result.replace(apiFileFolder(), implFileFolder(implFolder)); - } else if (templateName.endsWith("Factory.mustache")) { - int ix = result.lastIndexOf('/'); - result = result.substring(0, ix) + "/factories" + result.substring(ix, result.length() - 5) + "ServiceFactory.java"; - - result = result.replace(apiFileFolder(), implFileFolder(implFolder)); - } else if (templateName.endsWith("Service.mustache")) { - int ix = result.lastIndexOf('.'); - result = result.substring(0, ix) + "Service.java"; - } - - return result; - } - - - private String implFileFolder(String output) { - return outputFolder + "/" + output + "/" + apiPackage().replace('.', '/'); - } - - @Override - public boolean shouldOverwrite(String filename) { - return super.shouldOverwrite(filename) && !filename.endsWith("ServiceImpl.java") && !filename.endsWith("ServiceFactory.java"); - } - - public void setDateLibrary(String library) { - this.dateLibrary = library; - } - @Override public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { if(serializeBigDecimalAsString) { diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringBootServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringBootServerCodegen.java index 4b30062d7999..577b1bc3b933 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringBootServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringBootServerCodegen.java @@ -7,7 +7,7 @@ import io.swagger.models.Swagger; import java.io.File; import java.util.*; -public class SpringBootServerCodegen extends JavaClientCodegen implements CodegenConfig{ +public class SpringBootServerCodegen extends AbstractJavaCodegen { public static final String CONFIG_PACKAGE = "configPackage"; public static final String BASE_PACKAGE = "basePackage"; public static final String INTERFACE_ONLY = "interfaceOnly"; @@ -15,33 +15,24 @@ public class SpringBootServerCodegen extends JavaClientCodegen implements Codege public static final String JAVA_8 = "java8"; public static final String ASYNC = "async"; protected String title = "Petstore Server"; - protected String configPackage = ""; - protected String basePackage = ""; + protected String configPackage = "io.swagger.configuration"; + protected String basePackage = "io.swagger"; protected boolean interfaceOnly = false; protected boolean singleContentTypes = false; protected boolean java8 = false; protected boolean async = false; - protected String templateFileName = "api.mustache"; public SpringBootServerCodegen() { super(); outputFolder = "generated-code/javaSpringBoot"; - apiTemplateFiles.put(templateFileName, ".java"); apiTestTemplateFiles.clear(); // TODO: add test template embeddedTemplateDir = templateDir = "JavaSpringBoot"; apiPackage = "io.swagger.api"; modelPackage = "io.swagger.model"; - configPackage = "io.swagger.configuration"; invokerPackage = "io.swagger.api"; - basePackage = "io.swagger"; artifactId = "swagger-springboot-server"; - additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); - additionalProperties.put(CodegenConstants.GROUP_ID, groupId); - additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); - additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion); additionalProperties.put("title", title); - additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); additionalProperties.put(CONFIG_PACKAGE, configPackage); additionalProperties.put(BASE_PACKAGE, basePackage); @@ -52,7 +43,6 @@ public class SpringBootServerCodegen extends JavaClientCodegen implements Codege cliOptions.add(CliOption.newBoolean(JAVA_8, "use java8 default interface")); cliOptions.add(CliOption.newBoolean(ASYNC, "use async Callable controllers")); - supportedLibraries.clear(); supportedLibraries.put(DEFAULT_LIBRARY, "Default Spring Boot server stub."); supportedLibraries.put("j8-async", "Use async servlet feature and Java 8's default interface. Generating interface with service " + "declaration is useful when using Maven plugin. Just provide a implementation with @Controller to instantiate service." + @@ -80,6 +70,7 @@ public class SpringBootServerCodegen extends JavaClientCodegen implements Codege // clear model and api doc template as this codegen // does not support auto-generated markdown doc at the moment + //TODO: add doc templates modelDocTemplateFiles.remove("model_doc.mustache"); apiDocTemplateFiles.remove("api_doc.mustache"); @@ -107,7 +98,6 @@ public class SpringBootServerCodegen extends JavaClientCodegen implements Codege this.setAsync(Boolean.valueOf(additionalProperties.get(ASYNC).toString())); } - supportingFiles.clear(); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); diff --git a/modules/swagger-codegen/src/main/resources/JavaSpringBoot/api.mustache b/modules/swagger-codegen/src/main/resources/JavaSpringBoot/api.mustache index c3b3bb669083..48ac02fed778 100644 --- a/modules/swagger-codegen/src/main/resources/JavaSpringBoot/api.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaSpringBoot/api.mustache @@ -1,4 +1,4 @@ -package {{apiPackage}}; +package {{package}}; {{#imports}}import {{import}}; {{/imports}} diff --git a/modules/swagger-codegen/src/main/resources/JavaSpringBoot/apiController.mustache b/modules/swagger-codegen/src/main/resources/JavaSpringBoot/apiController.mustache index f9c03faafc12..2540bb75d79f 100644 --- a/modules/swagger-codegen/src/main/resources/JavaSpringBoot/apiController.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaSpringBoot/apiController.mustache @@ -1,4 +1,4 @@ -package {{apiPackage}}; +package {{package}}; {{^java8}} {{#imports}}import {{import}};