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:
Javier Velilla
2017-08-04 13:38:50 -03:00
committed by wing328
parent 10dc17e850
commit e4276853d7
12 changed files with 254 additions and 52 deletions

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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) + "\"";
}
}
}

View File

@@ -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}}");

View File

@@ -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

View File

@@ -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>

View File

@@ -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}}

View File

@@ -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

View File

@@ -0,0 +1,7 @@
{{>noteinfo}}
{{#models}}
{{#model}}
{{#isEnum}}{{>model_enum}}{{/isEnum}}{{^isEnum}}{{>model}}{{/isEnum}}
{{/model}}
{{/models}}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>