Skip to content

Commit

Permalink
[Java][Native] Support oneOf/anyOf schemas (#7263)
Browse files Browse the repository at this point in the history
* Java-native add models of oneOf/anyOf

* Java-native refresh samples

* Java-native add a sample project for openapi3
  • Loading branch information
bgong-mdsol committed Oct 15, 2020
1 parent f76d72e commit edf153e
Show file tree
Hide file tree
Showing 494 changed files with 39,916 additions and 759 deletions.
11 changes: 11 additions & 0 deletions bin/configs/java-native-openapi3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
generatorName: java
outputDir: samples/openapi3/client/petstore/java/native
library: native
inputSpec: modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml
templateDir: modules/openapi-generator/src/main/resources/Java
additionalProperties:
artifactId: petstore-openapi3-native
hideGenerationTimestamp: true
serverPort: "8082"
useOneOfDiscriminatorLookup: true
disallowAdditionalPropertiesIfNotPresent: false
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ public void processOpts() {
setJava8Mode(true);
additionalProperties.put("java8", "true");
supportingFiles.add(new SupportingFile("ApiResponse.mustache", invokerFolder, "ApiResponse.java"));
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
supportingFiles.add(new SupportingFile("AbstractOpenApiSchema.mustache", (sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar), "AbstractOpenApiSchema.java"));
forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
} else if (RESTEASY.equals(getLibrary())) {
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
Expand Down Expand Up @@ -536,8 +538,8 @@ public void processOpts() {
if (SERIALIZATION_LIBRARY_JACKSON.equals(getSerializationLibrary())) {
additionalProperties.put(SERIALIZATION_LIBRARY_JACKSON, "true");
additionalProperties.remove(SERIALIZATION_LIBRARY_GSON);
supportingFiles.add(new SupportingFile("RFC3339DateFormat.mustache", invokerFolder, "RFC3339DateFormat.java"));
if (!NATIVE.equals(getLibrary())) {
supportingFiles.add(new SupportingFile("RFC3339DateFormat.mustache", invokerFolder, "RFC3339DateFormat.java"));
if ("threetenbp".equals(dateLibrary) && !usePlayWS) {
supportingFiles.add(new SupportingFile("CustomInstantDeserializer.mustache", invokerFolder, "CustomInstantDeserializer.java"));
}
Expand Down Expand Up @@ -822,7 +824,6 @@ public Map<String, Object> postProcessModels(Map<String, Object> objs) {
imports2Classnames.put("JsonNullable", "org.openapitools.jackson.nullable.JsonNullable");
imports2Classnames.put("NoSuchElementException", "java.util.NoSuchElementException");
imports2Classnames.put("JsonIgnore", "com.fasterxml.jackson.annotation.JsonIgnore");

for (Map.Entry<String, String> entry : imports2Classnames.entrySet()) {
cm.imports.add(entry.getKey());
Map<String, String> importsItem = new HashMap<String, String>();
Expand All @@ -838,7 +839,7 @@ public Map<String, Object> postProcessModels(Map<String, Object> objs) {
CodegenModel cm = (CodegenModel) mo.get("model");

cm.getVendorExtensions().putIfAbsent("x-implements", new ArrayList<String>());
if (JERSEY2.equals(getLibrary())) {
if (JERSEY2.equals(getLibrary()) || NATIVE.equals(getLibrary())) {
cm.getVendorExtensions().put("x-implements", new ArrayList<String>());

if (cm.oneOf != null && !cm.oneOf.isEmpty() && cm.oneOf.contains("ModelNull")) {
Expand Down Expand Up @@ -978,7 +979,6 @@ public void addImportsToOneOfInterface(List<Map<String, String>> imports) {
for (String i : Arrays.asList("JsonSubTypes", "JsonTypeInfo")) {
Map<String, String> oneImport = new HashMap<>();
oneImport.put("import", importMapping.get(i));

if (!imports.contains(oneImport)) {
imports.add(oneImport);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
{{>licenseInfo}}

package {{invokerPackage}}.model;

import {{invokerPackage}}.ApiException;
import java.util.Objects;
import java.lang.reflect.Type;
import java.util.Map;
import javax.ws.rs.core.GenericType;

import com.fasterxml.jackson.annotation.JsonValue;

/**
* Abstract class for oneOf,anyOf schemas defined in OpenAPI spec
*/
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}
public abstract class AbstractOpenApiSchema {
// store the actual instance of the schema/object
private Object instance;
// is nullable
private Boolean isNullable;
// schema type (e.g. oneOf, anyOf)
private final String schemaType;
public AbstractOpenApiSchema(String schemaType, Boolean isNullable) {
this.schemaType = schemaType;
this.isNullable = isNullable;
}

/**
* Get the list of oneOf/anyOf composed schemas allowed to be stored in this object
*
* @return an instance of the actual schema/object
*/
public abstract Map<String, GenericType> getSchemas();

/**
* Get the actual instance
*
* @return an instance of the actual schema/object
*/
@JsonValue
public Object getActualInstance() {return instance;}

/**
* Set the actual instance
*
* @param instance the actual instance of the schema/object
*/
public void setActualInstance(Object instance) {this.instance = instance;}

/**
* Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well
*
* @return an instance of the actual schema/object
*/
public Object getActualInstanceRecursively() {
return getActualInstanceRecursively(this);
}

private Object getActualInstanceRecursively(AbstractOpenApiSchema object) {
if (object.getActualInstance() == null) {
return null;
} else if (object.getActualInstance() instanceof AbstractOpenApiSchema) {
return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance());
} else {
return object.getActualInstance();
}
}

/**
* Get the schema type (e.g. anyOf, oneOf)
*
* @return the schema type
*/
public String getSchemaType() {
return schemaType;
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class ").append(getClass()).append(" {\n");
sb.append(" instance: ").append(toIndentedString(instance)).append("\n");
sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n");
sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n");
sb.append("}");
return sb.toString();
}

/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}

public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AbstractOpenApiSchema a = (AbstractOpenApiSchema) o;
return Objects.equals(this.instance, a.instance) &&
Objects.equals(this.isNullable, a.isNullable) &&
Objects.equals(this.schemaType, a.schemaType);
}

@Override
public int hashCode() {
return Objects.hash(instance, isNullable, schemaType);
}

/**
* Is nullalble
*
* @return true if it's nullable
*/
public Boolean isNullable() {
if (Boolean.TRUE.equals(isNullable)) {
return Boolean.TRUE;
} else {
return Boolean.FALSE;
}
}

{{>libraries/native/additional_properties}}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package {{invokerPackage}};
import java.util.List;
import java.util.Map;
{{#caseInsensitiveResponseHeaders}}
import java.util.Map.Entry;
import java.util.Map.Entry;
import java.util.TreeMap;
{{/caseInsensitiveResponseHeaders}}

Expand Down
Loading

0 comments on commit edf153e

Please sign in to comment.