- Fixed inheritance support
This commit is contained in:
Jakub Malek 2016-06-01 15:04:18 +02:00 committed by Jakub Malek
parent 30b7eb7854
commit fc9b4501fc
7 changed files with 136 additions and 22 deletions

View File

@ -20,6 +20,7 @@ public class CodegenModel {
public List<CodegenProperty> requiredVars = new ArrayList<CodegenProperty>(); // a list of required properties
public List<CodegenProperty> optionalVars = new ArrayList<CodegenProperty>(); // a list of optional properties
public List<CodegenProperty> allVars;
public List<CodegenProperty> parentVars = new ArrayList<>();
public Map<String, Object> allowableValues;
// Sorted sets of required parameters.
@ -27,7 +28,7 @@ public class CodegenModel {
public Set<String> allMandatory;
public Set<String> imports = new TreeSet<String>();
public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum, hasRequired;
public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum, hasRequired,hasChildrens;
public ExternalDocs externalDocs;
public Map<String, Object> vendorExtensions;
@ -109,6 +110,10 @@ public class CodegenModel {
return false;
if (externalDocs != null ? !externalDocs.equals(that.externalDocs) : that.externalDocs != null)
return false;
if (!Objects.equals(hasChildrens, that.hasChildrens))
return false;
if (!Objects.equals(parentVars, that.parentVars))
return false;
return vendorExtensions != null ? vendorExtensions.equals(that.vendorExtensions) : that.vendorExtensions == null;
}
@ -145,6 +150,8 @@ public class CodegenModel {
result = 31 * result + (isEnum != null ? isEnum.hashCode() : 0);
result = 31 * result + (externalDocs != null ? externalDocs.hashCode() : 0);
result = 31 * result + (vendorExtensions != null ? vendorExtensions.hashCode() : 0);
result = 31 * result + Objects.hash(hasChildrens);
result = 31 * result + Objects.hash(parentVars);
return result;
}
}

View File

@ -2,8 +2,9 @@ package io.swagger.codegen;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class CodegenProperty {
public class CodegenProperty implements Cloneable {
public String baseName, complexType, getter, setter, description, datatype, datatypeWithEnum,
name, min, max, defaultValue, defaultValueWithParam, baseType, containerType;
@ -43,6 +44,8 @@ public class CodegenProperty {
public CodegenProperty items;
public Map<String, Object> vendorExtensions;
public Boolean hasValidation; // true if pattern, maximum, etc are set (only used in the mustache template)
public String parent;
public String parentClass;
@Override
public String toString() {
@ -105,6 +108,8 @@ public class CodegenProperty {
result = prime * result + ((isDateTime == null) ? 0 : isDateTime.hashCode());
result = prime * result + ((isMapContainer == null) ? 0 : isMapContainer.hashCode());
result = prime * result + ((isListContainer == null) ? 0 : isListContainer.hashCode());
result = prime * result + Objects.hashCode(parent);
result = prime * result + Objects.hashCode(parentClass);
return result;
}
@ -256,6 +261,21 @@ public class CodegenProperty {
if (this.isMapContainer != other.isMapContainer && (this.isMapContainer == null || !this.isMapContainer.equals(other.isMapContainer))) {
return false;
}
if (!Objects.equals(this.parent, other.parent)) {
return false;
}
if (!Objects.equals(this.parentClass, other.parentClass)) {
return false;
}
return true;
}
@Override
public CodegenProperty clone() {
try {
return (CodegenProperty) super.clone();
} catch (CloneNotSupportedException e) {
throw new IllegalStateException(e);
}
}
}

View File

@ -19,6 +19,7 @@ import static io.swagger.codegen.CodegenType.SERVER;
import static java.util.Arrays.asList;
import static java.util.UUID.randomUUID;
import static org.apache.commons.lang3.StringUtils.capitalize;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
@ -29,19 +30,24 @@ import io.swagger.models.properties.StringProperty;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Predicate;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
public class NancyFXServerCodegen extends AbstractCSharpCodegen {
private static final Logger log = LoggerFactory.getLogger(NancyFXServerCodegen.class);
@ -56,6 +62,8 @@ public class NancyFXServerCodegen extends AbstractCSharpCodegen {
private final String packageGuid = "{" + randomUUID().toString().toUpperCase() + "}";
private final Map<String, DependencyInfo> dependencies = new HashMap<>();
private final Set<String> parentModels = new HashSet<>();
private final Multimap<String, CodegenModel> parentChildrens = ArrayListMultimap.create();
private final BiMap<String, String> modelNameMapping = HashBiMap.create();
public NancyFXServerCodegen() {
@ -205,12 +213,89 @@ public class NancyFXServerCodegen extends AbstractCSharpCodegen {
}
}
@Override
public Map<String, Object> postProcessAllModels(final Map<String, Object> models) {
final Map<String, Object> processed = super.postProcessAllModels(models);
postProcessParentModels(models);
return processed;
}
private void postProcessParentModels(final Map<String, Object> models) {
log.info("Processing parents: " + parentModels);
for (final String parent : parentModels) {
final CodegenModel parentModel = modelByName(parent, models);
parentModel.hasChildrens = true;
final Collection<CodegenModel> childrens = parentChildrens.get(parent);
for (final CodegenModel child : childrens) {
processParentPropertiesInChildModel(parentModel, child);
}
}
}
private CodegenModel modelByName(final String name, final Map<String, Object> models) {
final Object data = models.get(name);
if (data instanceof Map) {
final Map<?, ?> dataMap = (Map<?, ?>) data;
final Object dataModels = dataMap.get("models");
if (dataModels instanceof List) {
final List<?> dataModelsList = (List<?>) dataModels;
for (final Object entry : dataModelsList) {
if (entry instanceof Map) {
final Map<?, ?> entryMap = (Map<?, ?>) entry;
final Object model = entryMap.get("model");
if (model instanceof CodegenModel) {
return (CodegenModel) model;
}
}
}
}
}
return null;
}
private void processParentPropertiesInChildModel(final CodegenModel parent, final CodegenModel child) {
final Map<String, CodegenProperty> childPropertiesByName = new HashMap<>(child.vars.size());
for (final CodegenProperty property : child.vars) {
childPropertiesByName.put(property.name, property);
}
CodegenProperty previousParentVar = null;
for (final CodegenProperty property : parent.vars) {
final CodegenProperty duplicatedByParent = childPropertiesByName.get(property.name);
if (duplicatedByParent != null) {
log.info(String.format("Property: '%s' in '%s' model is inherited from '%s'" ,
property.name, child.classname, parent.classname));
duplicatedByParent.parent = parent.name;
duplicatedByParent.parentClass = parent.classname;
final CodegenProperty parentVar = duplicatedByParent.clone();
parentVar.hasMore = false;
child.parentVars.add(parentVar);
if (previousParentVar != null) {
previousParentVar.hasMore = true;
}
previousParentVar = parentVar;
}
}
}
@Override
public void postProcessModelProperty(final CodegenModel model, final CodegenProperty property) {
super.postProcessModelProperty(model, property);
if (!isNullOrEmpty(model.parent)) {
parentModels.add(model.parent);
if (!parentChildrens.containsEntry(model.parent, model)) {
parentChildrens.put(model.parent, model);
}
}
}
@Override
public String toEnumVarName(final String name, final String datatype) {
final String enumName = camelize(
sanitizeName(name)
.replaceFirst("^_", "")
.replaceFirst("_$", ""));
.replaceFirst("_$", "")
.replaceAll("-", "_"));
final String result;
if (enumName.matches("\\d.*")) {
result = "_" + enumName;
@ -269,7 +354,7 @@ public class NancyFXServerCodegen extends AbstractCSharpCodegen {
@Override
public String toEnumName(final CodegenProperty property) {
return sanitizeName(camelize(property.name)) ;
return sanitizeName(camelize(property.name));
}
@Override

View File

@ -1 +1 @@
public enum {{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { {{#allowableValues}}{{#enumVars}}{{{name}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} };
public enum {{#parentClass}}{{parentClass}}{{/parentClass}}{{^parentClass}}{{classname}}{{/parentClass}}{{#datatypeWithEnum}}{{.}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { {{#allowableValues}}{{#enumVars}}{{{name}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} };

View File

@ -10,40 +10,42 @@ using NodaTime;
{{#models}}
{{#model}}
namespace {{packageName}}.{{packageContext}}.Models
{ {{#vars}}{{#isEnum}}
{{>innerModelEnum}}{{/isEnum}}{{#items.isEnum}}
{ {{#vars}}{{#isEnum}}{{^parent}}
{{>innerModelEnum}}{{/parent}}{{/isEnum}}{{#items.isEnum}}
{{#items}}{{>innerModelEnum}}{{/items}}{{/items.isEnum}}{{/vars}}
/// <summary>
/// {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}}
/// </summary>
public sealed class {{classname}}: {{#parent}}{{{parent}}}, {{/parent}} IEquatable<{{classname}}>
{ {{#vars}}
public {{^hasChildrens}}sealed {{/hasChildrens}}class {{classname}}: {{#parent}}{{{parent}}}, {{/parent}} IEquatable<{{classname}}>
{ {{#vars}}{{^parent}}
/// <summary>
/// {{^description}}{{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
/// </summary>
public {{>nullableDataType}} {{name}} { get; private set; }
{{/vars}}
{{/parent}}{{/vars}}
/// <summary>
/// Empty constructor required by some serializers.
/// Use {{classname}}.Builder() for instance creation instead.
/// </summary>
[Obsolete]
public {{classname}}() {}
private {{classname}}({{#vars}}{{>nullableDataType}} {{name}}{{#hasMore}}, {{/hasMore}}{{/vars}})
public {{classname}}(){{#parent}} : base({{/parent}}{{#parentVars}}null{{#hasMore}}, {{/hasMore}}{{/parentVars}}{{#parent}}){{/parent}}
{
{{#vars}}
}
{{#hasChildrens}}protected{{/hasChildrens}}{{^hasChildrens}}private{{/hasChildrens}} {{classname}}({{#vars}}{{>nullableDataType}} {{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}){{#parent}} : base({{#parentVars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/parentVars}}){{/parent}}
{
{{#vars}}{{^parent}}
this.{{name}} = {{name}};
{{/vars}}
{{/parent}}{{/vars}}
}
/// <summary>
/// Returns builder of {{classname}}.
/// </summary>
/// <returns>{{classname}}Builder</returns>
public static {{classname}}Builder Builder()
public static {{#parent}}new {{/parent}}{{classname}}Builder Builder()
{
return new {{classname}}Builder();
}
@ -53,7 +55,7 @@ namespace {{packageName}}.{{packageContext}}.Models
/// Use it to change properties.
/// </summary>
/// <returns>{{classname}}Builder</returns>
public {{classname}}Builder With()
public {{#parent}}new {{/parent}}{{classname}}Builder With()
{
return Builder()
{{#vars}}

View File

@ -10,14 +10,14 @@ using NodaTime;
{{#models}}
{{#model}}
namespace {{packageName}}.{{packageContext}}.Models
{ {{#vars}}{{#isEnum}}
{{>innerModelEnum}}{{/isEnum}}{{#items.isEnum}}
{ {{#vars}}{{#isEnum}}{{^parent}}
{{>innerModelEnum}}{{/parent}}{{/isEnum}}{{#items.isEnum}}
{{#items}}{{>innerModelEnum}}{{/items}}{{/items.isEnum}}{{/vars}}
/// <summary>
/// <summary>
/// {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}}
/// </summary>
public sealed class {{classname}}: {{#parent}}{{{parent}}}, {{/parent}} IEquatable<{{classname}}>
public {{^hasChildrens}}sealed {{/hasChildrens}}class {{classname}}: {{#parent}}{{{parent}}}, {{/parent}} IEquatable<{{classname}}>
{ {{#vars}}
/// <summary>
/// {{^description}}{{{name}}}{{/description}}{{#description}}{{description}}{{/description}}

View File

@ -1 +1 @@
{{&datatypeWithEnum}}{{#isEnum}}?{{/isEnum}}
{{#isEnum}}{{#parentClass}}{{parentClass}}{{/parentClass}}{{^parentClass}}{{classname}}{{/parentClass}}{{/isEnum}}{{&datatypeWithEnum}}{{#isEnum}}?{{/isEnum}}