Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.openapitools.codegen;

import java.util.*;

public class CodegenDiscriminator {
private String propertyName;
private Map<String, String> mapping;
private Set<MappedModel> mappedModels = new LinkedHashSet<>();

public String getPropertyName() {
return propertyName;
}

public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}

public Map<String, String> getMapping() {
return mapping;
}

public void setMapping(Map<String, String> mapping) {
this.mapping = mapping;
}

public Set<MappedModel> getMappedModels() {
return mappedModels;
}

public void setMappedModels(Set<MappedModel> mappedModels) {
this.mappedModels = mappedModels;
}

public static class MappedModel {
private String mappingName;
private String modelName;

public MappedModel(String mappingName, String modelName) {
this.mappingName = mappingName;
this.modelName = modelName;
}

public String getMappingName() {
return mappingName;
}

public void setMappingName(String mappingName) {
this.mappingName = mappingName;
}

public String getModelName() {
return modelName;
}

public void setModelName(String modelName) {
this.modelName = modelName;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MappedModel that = (MappedModel) o;
return Objects.equals(mappingName, that.mappingName) &&
Objects.equals(modelName, that.modelName);
}

@Override
public int hashCode() {
return Objects.hash(mappingName, modelName);
}
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CodegenDiscriminator that = (CodegenDiscriminator) o;
return Objects.equals(propertyName, that.propertyName) &&
Objects.equals(mapping, that.mapping) &&
Objects.equals(mappedModels, that.mappedModels);
}

@Override
public int hashCode() {
return Objects.hash(propertyName, mapping, mappedModels);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@
package org.openapitools.codegen;

import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.media.Discriminator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.Objects;

public class CodegenModel {
public String parent, parentSchema;
Expand All @@ -40,7 +39,7 @@ public class CodegenModel {
public String name, classname, title, description, classVarName, modelJson, dataType, xmlPrefix, xmlNamespace, xmlName;
public String classFilename; // store the class file name, mainly used for import
public String unescapedDescription;
public Discriminator discriminator;
public CodegenDiscriminator discriminator;
public String defaultValue;
public String arrayModelType;
public boolean isAlias; // Is this effectively an alias of another simple type
Expand Down Expand Up @@ -349,15 +348,15 @@ public void setUnescapedDescription(String unescapedDescription) {
this.unescapedDescription = unescapedDescription;
}

public Discriminator getDiscriminator() {
public CodegenDiscriminator getDiscriminator() {
return discriminator;
}

public String getDiscriminatorName() {
return discriminator == null ? null : discriminator.getPropertyName();
}

public void setDiscriminator(Discriminator discriminator) {
public void setDiscriminator(CodegenDiscriminator discriminator) {
this.discriminator = discriminator;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,15 @@
package org.openapitools.codegen;

import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.media.Discriminator;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.tags.Tag;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Arrays;

public class CodegenOperation {
public final List<CodegenProperty> responseHeaders = new ArrayList<CodegenProperty>();
Expand All @@ -40,7 +38,7 @@ public class CodegenOperation {
isRestful, isDeprecated;
public String path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse;
public Discriminator discriminator;
public CodegenDiscriminator discriminator;
public List<Map<String, String>> consumes, produces, prioritizedContentTypes;
public CodegenParameter bodyParam;
public List<CodegenParameter> allParams = new ArrayList<CodegenParameter>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.headers.Header;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.parameters.CookieParameter;
import io.swagger.v3.oas.models.parameters.HeaderParameter;
import io.swagger.v3.oas.models.parameters.Parameter;
Expand All @@ -43,6 +48,7 @@
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.CodegenDiscriminator.MappedModel;
import org.openapitools.codegen.examples.ExampleGenerator;
import org.openapitools.codegen.serializer.SerializerUtils;
import org.openapitools.codegen.utils.ModelUtils;
Expand All @@ -66,6 +72,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);
Expand Down Expand Up @@ -1469,6 +1476,10 @@ public CodegenModel fromModel(String name, Schema schema, Map<String, Schema> al

// unalias schema
schema = ModelUtils.unaliasSchema(allDefinitions, schema);
if (schema == null) {
LOGGER.warn("Schema {} not found", name);
return null;
}

CodegenModel m = CodegenModelFactory.newInstance(CodegenModelType.MODEL);

Expand All @@ -1489,7 +1500,7 @@ public CodegenModel fromModel(String name, Schema schema, Map<String, Schema> al
m.getVendorExtensions().putAll(schema.getExtensions());
}
m.isAlias = typeAliases.containsKey(name);
m.discriminator = schema.getDiscriminator();
m.discriminator = createDiscriminator(name, schema, allDefinitions);

if (schema.getXml() != null) {
m.xmlPrefix = schema.getXml().getPrefix();
Expand All @@ -1516,7 +1527,7 @@ public CodegenModel fromModel(String name, Schema schema, Map<String, Schema> al
int modelImplCnt = 0; // only one inline object allowed in a ComposedModel
for (Schema innerModel : composed.getAllOf()) {
if (m.discriminator == null) {
m.discriminator = schema.getDiscriminator();
m.discriminator = createDiscriminator(name, schema, allDefinitions);
}
if (innerModel.getXml() != null) {
m.xmlPrefix = innerModel.getXml().getPrefix();
Expand Down Expand Up @@ -1631,6 +1642,34 @@ public CodegenModel fromModel(String name, Schema schema, Map<String, Schema> al
return m;
}

private CodegenDiscriminator createDiscriminator(String schemaName, Schema schema, Map<String, Schema> allDefinitions) {
if(schema.getDiscriminator() == null) {
return null;
}
CodegenDiscriminator discriminator = new CodegenDiscriminator();
discriminator.setPropertyName(schema.getDiscriminator().getPropertyName());
discriminator.setMapping(schema.getDiscriminator().getMapping());
if(schema.getDiscriminator().getMapping() != null && !schema.getDiscriminator().getMapping().isEmpty()) {
for (Entry<String, String> e : schema.getDiscriminator().getMapping().entrySet()) {
String name = ModelUtils.getSimpleRef(e.getValue());
discriminator.getMappedModels().add(new MappedModel(e.getKey(), name));
}
} else {
allDefinitions.forEach((childName, child) -> {
if (child instanceof ComposedSchema && ((ComposedSchema) child).getAllOf() != null) {
Set<String> parentSchemas = ((ComposedSchema) child).getAllOf().stream()
.filter(s -> s.get$ref() != null)
.map(s -> ModelUtils.getSimpleRef(s.get$ref()))
.collect(Collectors.toSet());
if (parentSchemas.contains(schemaName)) {
discriminator.getMappedModels().add(new MappedModel(childName, childName));
}
}
});
}
return discriminator;
}

protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
addParentContainer(codegenModel, codegenModel.name, schema);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,25 +523,6 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
}
}

@SuppressWarnings("unchecked")
@Override
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
Map<String, Object> allProcessedModels = super.postProcessAllModels(objs);
if (!additionalProperties.containsKey("gsonFactoryMethod")) {
List<Object> allModels = new ArrayList<Object>();
for (String name : allProcessedModels.keySet()) {
Map<String, Object> models = (Map<String, Object>) allProcessedModels.get(name);
try {
allModels.add(((List<Object>) models.get("models")).get(0));
} catch (Exception e) {
e.printStackTrace();
}
}
additionalProperties.put("parent", modelInheritanceSupportInGson(allModels));
}
return allProcessedModels;
}

@Override
public Map<String, Object> postProcessModelsEnum(Map<String, Object> objs) {
objs = super.postProcessModelsEnum(objs);
Expand All @@ -564,34 +545,6 @@ public Map<String, Object> postProcessModelsEnum(Map<String, Object> objs) {
return objs;
}

public static List<Map<String, Object>> modelInheritanceSupportInGson(List<?> allModels) {
Map<CodegenModel, List<CodegenModel>> byParent = new LinkedHashMap<>();
for (Object model : allModels) {
Map entry = (Map) model;
CodegenModel parent = ((CodegenModel)entry.get("model")).parentModel;
if(null!= parent) {
byParent.computeIfAbsent(parent, k -> new LinkedList<>()).add((CodegenModel)entry.get("model"));
}
}
List<Map<String, Object>> parentsList = new ArrayList<>();
for (CodegenModel parentModel : byParent.keySet()) {
List<Map<String, Object>> childrenList = new ArrayList<>();
Map<String, Object> parent = new HashMap<>();
parent.put("classname", parentModel.classname);
List<CodegenModel> childrenModels = byParent.get(parentModel);
for (CodegenModel model : childrenModels) {
Map<String, Object> child = new HashMap<>();
child.put("name", model.name);
child.put("classname", model.classname);
childrenList.add(child);
}
parent.put("children", childrenList);
parent.put("discriminator", parentModel.discriminator);
parentsList.add(parent);
}
return parentsList;
}

public void setUseRxJava(boolean useRxJava) {
this.useRxJava = useRxJava;
doNotUseRx = false;
Expand Down
13 changes: 6 additions & 7 deletions modules/openapi-generator/src/main/resources/Java/JSON.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,20 @@ public class JSON {

public static GsonBuilder createGson() {
GsonFireBuilder fireBuilder = new GsonFireBuilder()
{{#parent}}
.registerTypeSelector({{classname}}.class, new TypeSelector() {
{{#models}}{{#model}}{{#discriminator}} .registerTypeSelector({{classname}}.class, new TypeSelector() {
@Override
public Class getClassForElement(JsonElement readElement) {
Map classByDiscriminatorValue = new HashMap();
{{#children}}
classByDiscriminatorValue.put("{{name}}".toUpperCase(), {{classname}}.class);
{{/children}}
{{#mappedModels}}
classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(), {{modelName}}.class);
{{/mappedModels}}
classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class);
return getClassByDiscriminator(
classByDiscriminatorValue,
getDiscriminatorValue(readElement, "{{{discriminatorName}}}"));
getDiscriminatorValue(readElement, "{{{propertyName}}}"));
}
})
{{/parent}}
{{/discriminator}}{{/model}}{{/models}}
;
GsonBuilder builder = fireBuilder.createGsonBuilder();
{{#disableHtmlEscaping}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,20 @@ public class JSON {

public static GsonBuilder createGson() {
GsonFireBuilder fireBuilder = new GsonFireBuilder()
{{#parent}}
.registerTypeSelector({{classname}}.class, new TypeSelector() {
{{#models}}{{#model}}{{#discriminator}} .registerTypeSelector({{classname}}.class, new TypeSelector() {
@Override
public Class getClassForElement(JsonElement readElement) {
Map classByDiscriminatorValue = new HashMap();
{{#children}}
classByDiscriminatorValue.put("{{name}}".toUpperCase(), {{classname}}.class);
{{/children}}
{{#mappedModels}}
classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(), {{modelName}}.class);
{{/mappedModels}}
classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class);
return getClassByDiscriminator(
classByDiscriminatorValue,
getDiscriminatorValue(readElement, "{{{discriminatorName}}}"));
getDiscriminatorValue(readElement, "{{{propertyName}}}"));
}
})
{{/parent}}
{{/discriminator}}{{/model}}{{/models}}
;
return fireBuilder.createGsonBuilder();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{{#jackson}}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminatorName}}}", visible = true )

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminatorName}}}", visible = true)
@JsonSubTypes({
{{#children}}
@JsonSubTypes.Type(value = {{classname}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"),
{{/children}}
{{#discriminator.mappedModels}}
@JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"),
{{/discriminator.mappedModels}}
}){{/jackson}}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{{#jackson}}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminatorName}}}", visible = true )

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminatorName}}}", visible = true)
@JsonSubTypes({
{{#children}}
@JsonSubTypes.Type(value = {{classname}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"),
{{/children}}
{{#discriminator.mappedModels}}
@JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"),
{{/discriminator.mappedModels}}
}){{/jackson}}
Loading