forked from loafle/openapi-generator-original
Fixed typo in the Abstract Eiffel class. (#6239)
Fixed typo in shell script Added support for Outer Enums, inner enums not supported. Added missing UUID library in ecf template. Improved Model inheritance.
This commit is contained in:
@@ -26,6 +26,6 @@ fi
|
||||
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l eiffel -o samples/client/petstore/eiffel/"
|
||||
args="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l eiffel -o samples/client/petstore/eiffel/"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
java $JAVA_OPTS -jar $executable $args
|
||||
|
||||
@@ -2,7 +2,6 @@ package io.swagger.codegen.languages;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -27,16 +26,18 @@ import io.swagger.codegen.CodegenParameter;
|
||||
import io.swagger.codegen.CodegenProperty;
|
||||
import io.swagger.codegen.DefaultCodegen;
|
||||
import io.swagger.codegen.utils.ModelUtils;
|
||||
import io.swagger.models.Model;
|
||||
import io.swagger.models.properties.ArrayProperty;
|
||||
import io.swagger.models.properties.MapProperty;
|
||||
import io.swagger.models.properties.Property;
|
||||
import io.swagger.util.Json;
|
||||
|
||||
public abstract class AbstractEiffelCogegen extends DefaultCodegen implements CodegenConfig {
|
||||
public abstract class AbstractEiffelCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
private final Set<String> parentModels = new HashSet<>();
|
||||
private final Multimap<String, CodegenModel> childrenByParent = ArrayListMultimap.create();
|
||||
|
||||
public AbstractEiffelCogegen(){
|
||||
|
||||
public AbstractEiffelCodegen(){
|
||||
super();
|
||||
setReservedWordsLowerCase(Arrays.asList(
|
||||
// language reserved words
|
||||
@@ -384,32 +385,34 @@ public abstract class AbstractEiffelCogegen extends DefaultCodegen implements Co
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
// remove model imports to avoid error
|
||||
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
|
||||
final String prefix = modelPackage();
|
||||
Iterator<Map<String, String>> iterator = imports.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
String _import = iterator.next().get("import");
|
||||
if (_import.startsWith(prefix))
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
// recursively add import for mapping one type to multiple imports
|
||||
List<Map<String, String>> recursiveImports = (List<Map<String, String>>) objs.get("imports");
|
||||
if (recursiveImports == null)
|
||||
return objs;
|
||||
|
||||
ListIterator<Map<String, String>> listIterator = imports.listIterator();
|
||||
while (listIterator.hasNext()) {
|
||||
String _import = listIterator.next().get("import");
|
||||
// if the import package happens to be found in the importMapping
|
||||
// (key)
|
||||
// add the corresponding import package to the list
|
||||
if (importMapping.containsKey(_import)) {
|
||||
listIterator.add(createMapping("import", importMapping.get(_import)));
|
||||
}
|
||||
}
|
||||
|
||||
return objs;
|
||||
// List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
|
||||
// final String prefix = modelPackage();
|
||||
// Iterator<Map<String, String>> iterator = imports.iterator();
|
||||
// while (iterator.hasNext()) {
|
||||
// String _import = iterator.next().get("import");
|
||||
// if (_import.startsWith(prefix))
|
||||
// iterator.remove();
|
||||
// }
|
||||
//
|
||||
// // recursively add import for mapping one type to multiple imports
|
||||
// List<Map<String, String>> recursiveImports = (List<Map<String, String>>) objs.get("imports");
|
||||
// if (recursiveImports == null)
|
||||
// return objs;
|
||||
//
|
||||
// ListIterator<Map<String, String>> listIterator = imports.listIterator();
|
||||
// while (listIterator.hasNext()) {
|
||||
// String _import = listIterator.next().get("import");
|
||||
// // if the import package happens to be found in the importMapping
|
||||
// // (key)
|
||||
// // add the corresponding import package to the list
|
||||
// if (importMapping.containsKey(_import)) {
|
||||
// listIterator.add(createMapping("import", importMapping.get(_import)));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return objs;
|
||||
// process enum in models
|
||||
return postProcessModelsEnum(objs);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -439,14 +442,76 @@ public abstract class AbstractEiffelCogegen extends DefaultCodegen implements Co
|
||||
for (final CodegenProperty childProperty : child.vars) {
|
||||
childPropertiesByName.put(childProperty.name, childProperty);
|
||||
}
|
||||
for (final CodegenProperty parentProperty : parent.vars) {
|
||||
final CodegenProperty duplicatedByParent = childPropertiesByName.get(parentProperty.name);
|
||||
if (duplicatedByParent != null) {
|
||||
duplicatedByParent.isInherited = true;
|
||||
if (parent != null) {
|
||||
for (final CodegenProperty parentProperty : parent.vars) {
|
||||
final CodegenProperty duplicatedByParent = childPropertiesByName.get(parentProperty.name);
|
||||
if (duplicatedByParent != null) {
|
||||
duplicatedByParent.isInherited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
|
||||
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
|
||||
if (allDefinitions != null && codegenModel.parentSchema != null && codegenModel.hasEnums) {
|
||||
final Model parentModel = allDefinitions.get(codegenModel.parentSchema);
|
||||
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel);
|
||||
codegenModel = AbstractEiffelCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel);
|
||||
}
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
|
||||
// This generator uses inline classes to define enums, which breaks when
|
||||
// dealing with models that have subTypes. To clean this up, we will analyze
|
||||
// the parent and child models, look for enums that match, and remove
|
||||
// them from the child models and leave them in the parent.
|
||||
// Because the child models extend the parents, the enums will be available via the parent.
|
||||
|
||||
// Only bother with reconciliation if the parent model has enums.
|
||||
if (!parentCodegenModel.hasEnums) {
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
// Get the properties for the parent and child models
|
||||
final List<CodegenProperty> parentModelCodegenProperties = parentCodegenModel.vars;
|
||||
List<CodegenProperty> 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<CodegenProperty> iterator = codegenProperties.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
CodegenProperty codegenProperty = iterator.next();
|
||||
if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) {
|
||||
// We found an enum in the child class that is
|
||||
// a duplicate of the one in the parent, so remove it.
|
||||
iterator.remove();
|
||||
removedChildEnum = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(removedChildEnum) {
|
||||
// If we removed an entry from this model's vars, we need to ensure hasMore is updated
|
||||
int count = 0, numVars = codegenProperties.size();
|
||||
for(CodegenProperty codegenProperty : codegenProperties) {
|
||||
count += 1;
|
||||
codegenProperty.hasMore = (count < numVars) ? true : false;
|
||||
}
|
||||
codegenModel.vars = codegenProperties;
|
||||
}
|
||||
return codegenModel;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean needToImport(String type) {
|
||||
return !defaultIncludes.contains(type) && !languageSpecificPrimitives.contains(type);
|
||||
@@ -501,7 +566,41 @@ public abstract class AbstractEiffelCogegen extends DefaultCodegen implements Co
|
||||
} else {
|
||||
return operationId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update property for array(list) container
|
||||
* @param property Codegen property
|
||||
* @param innerProperty Codegen inner property of map or list
|
||||
*/
|
||||
@Override
|
||||
protected void updatePropertyForArray(CodegenProperty property, CodegenProperty innerProperty) {
|
||||
if (innerProperty == null) {
|
||||
LOGGER.warn("skipping invalid array property " + Json.pretty(property));
|
||||
return;
|
||||
}
|
||||
property.dataFormat = innerProperty.dataFormat;
|
||||
if (!languageSpecificPrimitives.contains(innerProperty.baseType)) {
|
||||
property.complexType = innerProperty.baseType;
|
||||
} else {
|
||||
property.isPrimitiveType = true;
|
||||
}
|
||||
property.items = innerProperty;
|
||||
// inner item is Enum
|
||||
if (isPropertyInnerMostEnum(property)) {
|
||||
// We use the data type instead of the Enum class.
|
||||
// at the moment is not supported.
|
||||
|
||||
// isEnum is set to true when the type is an enum
|
||||
// or the inner type of an array/map is an enum
|
||||
//property.isEnum = true;
|
||||
// update datatypeWithEnum and default value for array
|
||||
// e.g. List<string> => List<StatusEnum>
|
||||
//updateDataTypeWithEnumForArray(property);
|
||||
// set allowable values to enum values (including array/map of enum)
|
||||
//property.allowableValues = getInnerEnumAllowableValues(property);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,19 @@
|
||||
package io.swagger.codegen.languages;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.swagger.codegen.CodegenConstants;
|
||||
import io.swagger.codegen.CodegenProperty;
|
||||
import io.swagger.codegen.CodegenType;
|
||||
import io.swagger.codegen.SupportingFile;
|
||||
|
||||
public class EiffelClientCodegen extends AbstractEiffelCogegen {
|
||||
public class EiffelClientCodegen extends AbstractEiffelCodegen {
|
||||
static Logger LOGGER = LoggerFactory.getLogger(EiffelClientCodegen.class);
|
||||
|
||||
protected String libraryTarget = "swagger_eiffel_client";
|
||||
@@ -42,10 +45,9 @@ public class EiffelClientCodegen extends AbstractEiffelCogegen {
|
||||
super();
|
||||
uuid = UUID.randomUUID();
|
||||
uuidTest = UUID.randomUUID();
|
||||
;
|
||||
outputFolder = "generated-code/Eiffel";
|
||||
modelDocTemplateFiles.put("model_doc.mustache", ".md");
|
||||
modelTemplateFiles.put("model.mustache", ".e");
|
||||
modelTemplateFiles.put("model_generic.mustache", ".e");
|
||||
apiTemplateFiles.put("api.mustache", ".e");
|
||||
apiTestTemplateFiles.put("test/api_test.mustache", ".e");
|
||||
apiDocTemplateFiles.put("api_doc.mustache", ".md");
|
||||
@@ -155,6 +157,53 @@ public class EiffelClientCodegen extends AbstractEiffelCogegen {
|
||||
public void setPackageVersion(String packageVersion) {
|
||||
this.packageVersion = packageVersion;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toEnumName(CodegenProperty property) {
|
||||
return sanitizeName(property.name).toUpperCase() + "_ENUM";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String value, String datatype) {
|
||||
if (value.length() == 0) {
|
||||
return "EMPTY";
|
||||
}
|
||||
|
||||
// for symbol, e.g. $, #
|
||||
if (getSymbolName(value) != null) {
|
||||
return getSymbolName(value).toUpperCase();
|
||||
}
|
||||
|
||||
// number
|
||||
if ("INTEGER_32".equals(datatype) || "INTEGER_64".equals(datatype) ||
|
||||
"REAL_32".equals(datatype) || "REAL_64".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+", "_").toLowerCase();
|
||||
if (var.matches("\\d.*")) {
|
||||
return "val_" + var;
|
||||
} else if (var.startsWith("_")){
|
||||
return "val" + var;
|
||||
} else {
|
||||
return "val_" + var;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumValue(String value, String datatype) {
|
||||
if ("INTEGER_32".equals(datatype) || "INTEGER_64".equals(datatype) ||
|
||||
"REAL_32".equals(datatype) || "REAL_64".equals(datatype)) {
|
||||
return value;
|
||||
} else {
|
||||
return "\"" + escapeText(value) + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ feature -- API Access
|
||||
{{#queryParams}}
|
||||
l_request.fill_query_params(api_client.parameter_to_tuple("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}}));
|
||||
{{/queryParams}}
|
||||
|
||||
{{#headerParams}}
|
||||
if attached {{paramName}} as l_{{paramName}} then
|
||||
l_request.add_header(l_{{paramName}}.out,"{{baseName}}");
|
||||
|
||||
@@ -123,7 +123,7 @@ feature -- Helper: OAuth Authentication
|
||||
|
||||
feature -- Query Parameter Helpers
|
||||
|
||||
parameter_to_tuple (a_collection_format, a_name: STRING; a_value: ANY): LIST [TUPLE [name: STRING; value: STRING]]
|
||||
parameter_to_tuple (a_collection_format, a_name: STRING; a_value: detachable ANY): LIST [TUPLE [name: STRING; value: STRING]]
|
||||
-- A list of tuples with name and valule.
|
||||
-- collectionFormat collection format (e.g. csv, tsv)
|
||||
-- name Name
|
||||
@@ -175,7 +175,12 @@ feature -- Query Parameter Helpers
|
||||
end
|
||||
else
|
||||
create {ARRAYED_LIST [TUPLE [name: STRING; value: STRING]]} Result.make (1)
|
||||
Result.force ([a_name,a_value.out])
|
||||
if attached a_value then
|
||||
Result.force ([a_name,a_value.out])
|
||||
else
|
||||
Result.force ([a_name,""])
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<library name="http_client" location="$ISE_LIBRARY\contrib\library\network\http_client\http_client-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri-safe.ecf"/>
|
||||
<library name="uuid" location="$ISE_LIBRARY\library\uuid\uuid.ecf"/>
|
||||
<cluster name="client" location=".\src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
{{>noteinfo}}
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
|
||||
class {{classname}}
|
||||
|
||||
inherit
|
||||
@@ -18,7 +14,12 @@ inherit
|
||||
{{#parent}}
|
||||
{{{parent}}}
|
||||
rename
|
||||
out as out_{{{parentSchema}}}
|
||||
out as out_{{{parentSchema}}},
|
||||
is_equal as is_equal_{{{parentSchema}}},
|
||||
copy as copy_{{{parentSchema}}}
|
||||
select
|
||||
is_equal_{{{parentSchema}}},
|
||||
copy_{{{parentSchema}}}
|
||||
end
|
||||
{{/parent}}
|
||||
|
||||
@@ -103,5 +104,3 @@ feature -- Change Element
|
||||
{{/vars}}
|
||||
end
|
||||
end
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
@@ -0,0 +1,36 @@
|
||||
class {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}
|
||||
|
||||
feature -- Access
|
||||
|
||||
value: detachable {{dataType}}
|
||||
-- enumerated value.
|
||||
note
|
||||
option: stable
|
||||
attribute
|
||||
end
|
||||
|
||||
feature -- Enum
|
||||
|
||||
{{#allowableValues}}
|
||||
{{#enumVars}}
|
||||
{{{name}}}: {{classname}}
|
||||
once
|
||||
create Result
|
||||
Result.set_value ({{{value}}}){{^-last}}{{/-last}}{{#-last}}{{/-last}}
|
||||
end
|
||||
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}}
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
set_value (a_val: like value)
|
||||
-- Set `value' with `a_value'.
|
||||
do
|
||||
value := a_val
|
||||
ensure
|
||||
value_set: value = a_val
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
{{>noteinfo}}
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
{{#isEnum}}{{>model_enum}}{{/isEnum}}{{^isEnum}}{{>model}}{{/isEnum}}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<library name="api_client" location="..\api_client.ecf" readonly="false"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="uuid" location="$ISE_LIBRARY\library\uuid\uuid.ecf"/>
|
||||
<cluster name="test" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="swagger_eiffel_client" uuid="1eca0519-e046-46a8-9a4a-e7b165399022" library_target="swagger_eiffel_client">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="swagger_eiffel_client" uuid="e892c29a-3caa-456b-bc97-f488bba434b9" library_target="swagger_eiffel_client">
|
||||
<target name="swagger_eiffel_client">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
@@ -19,6 +19,7 @@
|
||||
<library name="http_client" location="$ISE_LIBRARY\contrib\library\network\http_client\http_client-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri-safe.ecf"/>
|
||||
<library name="uuid" location="$ISE_LIBRARY\library\uuid\uuid.ecf"/>
|
||||
<cluster name="client" location=".\src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="test" uuid="852c8325-690a-42c3-b22e-21a39d723d98">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="test" uuid="28bb8709-c181-416f-8c3e-9eea7157da9f">
|
||||
<target name="test">
|
||||
<root feature="make" class="APPLICATION"/>
|
||||
<file_rule>
|
||||
@@ -16,6 +16,8 @@
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<library name="api_client" location="..\api_client.ecf" readonly="false"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="uuid" location="$ISE_LIBRARY\library\uuid\uuid.ecf"/>
|
||||
<cluster name="test" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
Reference in New Issue
Block a user