Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(openapi-generator): Allow for primitives in anyOf/oneOf component schema definitions #681

Merged
merged 20 commits into from
Jan 29, 2025
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
2 changes: 2 additions & 0 deletions datamodel/openapi/openapi-api-sample/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,10 @@
<pojoBuildMethodName />
<pojoConstructorVisibility>protected</pojoConstructorVisibility>
<useOneOfInterfaces>true</useOneOfInterfaces>
<useOneOfCreators>true</useOneOfCreators>
<enumUnknownDefaultCase>true</enumUnknownDefaultCase>
</additionalProperties>
<enableOneOfAnyOfGeneration>true</enableOneOfAnyOfGeneration>
Copy link
Contributor

@CharlesDuboisSAP CharlesDuboisSAP Jan 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why were the other classes (OneOf, AnyOf) not affected by this change?
Why wasn't it there in the first place?

Copy link
Contributor Author

@newtork newtork Jan 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omg, I went deep into the rabbit hole. I found that our check for (unsupported) anyof / oneof was not sufficient!

  • oneOf and anyOf are not checked when they are part of schema root; only when they are deeper in object hierarchy, e.g. when being part of properties fields

See #checkForValidatorsInSchema(JsonNode)

image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was intentional, because on the root level the generation was already working for some cases. IIRC

</configuration>
</plugin>
<!-- Enable formatter to always run on the generated code -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public class AllOf
@JsonProperty( "color" )
private String color;

@JsonProperty( "flavor" )
private FantaFlavor flavor;

@JsonAnySetter
@JsonAnyGetter
private final Map<String, Object> cloudSdkCustomFields = new LinkedHashMap<>();
Expand Down Expand Up @@ -164,6 +167,42 @@ public void setColor( @Nullable final String color )
this.color = color;
}

/**
* Set the flavor of this {@link AllOf} instance and return the same instance.
*
* @param flavor
* The flavor of this {@link AllOf}
* @return The same instance of this {@link AllOf} class
*/
@Nonnull
public AllOf flavor( @Nullable final FantaFlavor flavor )
{
this.flavor = flavor;
return this;
}

/**
* Get flavor
*
* @return flavor The flavor of this {@link AllOf} instance.
*/
@Nonnull
public FantaFlavor getFlavor()
{
return flavor;
}

/**
* Set the flavor of this {@link AllOf} instance.
*
* @param flavor
* The flavor of this {@link AllOf}
*/
public void setFlavor( @Nullable final FantaFlavor flavor )
{
this.flavor = flavor;
}

/**
* Get the names of the unrecognizable properties of the {@link AllOf}.
*
Expand Down Expand Up @@ -223,13 +262,14 @@ public boolean equals( @Nullable final java.lang.Object o )
return Objects.equals(this.cloudSdkCustomFields, allOf.cloudSdkCustomFields)
&& Objects.equals(this.sodaType, allOf.sodaType)
&& Objects.equals(this.caffeine, allOf.caffeine)
&& Objects.equals(this.color, allOf.color);
&& Objects.equals(this.color, allOf.color)
&& Objects.equals(this.flavor, allOf.flavor);
}

@Override
public int hashCode()
{
return Objects.hash(sodaType, caffeine, color, cloudSdkCustomFields);
return Objects.hash(sodaType, caffeine, color, flavor, cloudSdkCustomFields);
}

@Override
Expand All @@ -241,6 +281,7 @@ public String toString()
sb.append(" sodaType: ").append(toIndentedString(sodaType)).append("\n");
sb.append(" caffeine: ").append(toIndentedString(caffeine)).append("\n");
sb.append(" color: ").append(toIndentedString(color)).append("\n");
sb.append(" flavor: ").append(toIndentedString(flavor)).append("\n");
cloudSdkCustomFields
.forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
sb.append("}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public class AnyOf
@JsonProperty( "color" )
private String color;

@JsonProperty( "flavor" )
private FantaFlavor flavor;

@JsonAnySetter
@JsonAnyGetter
private final Map<String, Object> cloudSdkCustomFields = new LinkedHashMap<>();
Expand Down Expand Up @@ -164,6 +167,42 @@ public void setColor( @Nullable final String color )
this.color = color;
}

/**
* Set the flavor of this {@link AnyOf} instance and return the same instance.
*
* @param flavor
* The flavor of this {@link AnyOf}
* @return The same instance of this {@link AnyOf} class
*/
@Nonnull
public AnyOf flavor( @Nullable final FantaFlavor flavor )
{
this.flavor = flavor;
return this;
}

/**
* Get flavor
*
* @return flavor The flavor of this {@link AnyOf} instance.
*/
@Nonnull
public FantaFlavor getFlavor()
{
return flavor;
}

/**
* Set the flavor of this {@link AnyOf} instance.
*
* @param flavor
* The flavor of this {@link AnyOf}
*/
public void setFlavor( @Nullable final FantaFlavor flavor )
{
this.flavor = flavor;
}

/**
* Get the names of the unrecognizable properties of the {@link AnyOf}.
*
Expand Down Expand Up @@ -223,13 +262,14 @@ public boolean equals( @Nullable final java.lang.Object o )
return Objects.equals(this.cloudSdkCustomFields, anyOf.cloudSdkCustomFields)
&& Objects.equals(this.sodaType, anyOf.sodaType)
&& Objects.equals(this.caffeine, anyOf.caffeine)
&& Objects.equals(this.color, anyOf.color);
&& Objects.equals(this.color, anyOf.color)
&& Objects.equals(this.flavor, anyOf.flavor);
}

@Override
public int hashCode()
{
return Objects.hash(sodaType, caffeine, color, cloudSdkCustomFields);
return Objects.hash(sodaType, caffeine, color, flavor, cloudSdkCustomFields);
}

@Override
Expand All @@ -241,6 +281,7 @@ public String toString()
sb.append(" sodaType: ").append(toIndentedString(sodaType)).append("\n");
sb.append(" caffeine: ").append(toIndentedString(caffeine)).append("\n");
sb.append(" color: ").append(toIndentedString(color)).append("\n");
sb.append(" flavor: ").append(toIndentedString(flavor)).append("\n");
cloudSdkCustomFields
.forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
sb.append("}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public class Fanta implements OneOf, OneOfWithDiscriminator, OneOfWithDiscrimina
@JsonProperty( "color" )
private String color;

@JsonProperty( "flavor" )
private FantaFlavor flavor;

@JsonAnySetter
@JsonAnyGetter
private final Map<String, Object> cloudSdkCustomFields = new LinkedHashMap<>();
Expand Down Expand Up @@ -125,6 +128,42 @@ public void setColor( @Nullable final String color )
this.color = color;
}

/**
* Set the flavor of this {@link Fanta} instance and return the same instance.
*
* @param flavor
* The flavor of this {@link Fanta}
* @return The same instance of this {@link Fanta} class
*/
@Nonnull
public Fanta flavor( @Nullable final FantaFlavor flavor )
{
this.flavor = flavor;
return this;
}

/**
* Get flavor
*
* @return flavor The flavor of this {@link Fanta} instance.
*/
@Nonnull
public FantaFlavor getFlavor()
{
return flavor;
}

/**
* Set the flavor of this {@link Fanta} instance.
*
* @param flavor
* The flavor of this {@link Fanta}
*/
public void setFlavor( @Nullable final FantaFlavor flavor )
{
this.flavor = flavor;
}

/**
* Get the names of the unrecognizable properties of the {@link Fanta}.
*
Expand Down Expand Up @@ -183,13 +222,14 @@ public boolean equals( @Nullable final java.lang.Object o )
final Fanta fanta = (Fanta) o;
return Objects.equals(this.cloudSdkCustomFields, fanta.cloudSdkCustomFields)
&& Objects.equals(this.sodaType, fanta.sodaType)
&& Objects.equals(this.color, fanta.color);
&& Objects.equals(this.color, fanta.color)
&& Objects.equals(this.flavor, fanta.flavor);
}

@Override
public int hashCode()
{
return Objects.hash(sodaType, color, cloudSdkCustomFields);
return Objects.hash(sodaType, color, flavor, cloudSdkCustomFields);
}

@Override
Expand All @@ -200,6 +240,7 @@ public String toString()
sb.append("class Fanta {\n");
sb.append(" sodaType: ").append(toIndentedString(sodaType)).append("\n");
sb.append(" color: ").append(toIndentedString(color)).append("\n");
sb.append(" flavor: ").append(toIndentedString(flavor)).append("\n");
cloudSdkCustomFields
.forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
sb.append("}");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2025 SAP SE or an SAP affiliate company. All rights reserved.
*/

/*
* SodaStore API
* API for managing soda products and orders in SodaStore.
*
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

package com.sap.cloud.sdk.datamodel.openapi.sample.model;

import javax.annotation.Nonnull;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

/**
* FantaFlavor
*/
public interface FantaFlavor
{
/**
* Helper class to create a Integer that implements {@link FantaFlavor}.
*/
record InnerInteger(@com.fasterxml.jackson.annotation.JsonValue @Nonnull Integer value) implements FantaFlavor {}

/**
* Creator to enable deserialization of a Integer.
*
* @param val
* the value to use
* @return a new instance of {@link InnerInteger}.
*/
@com.fasterxml.jackson.annotation.JsonCreator
@Nonnull
static InnerInteger create( @Nonnull final Integer val )
{
return new InnerInteger(val);
}

/**
* Helper class to create a FantaFlavorOneOf that implements {@link FantaFlavor}.
*/
record InnerFantaFlavorOneOf(@com.fasterxml.jackson.annotation.JsonValue @Nonnull FantaFlavorOneOf value) implements FantaFlavor {}

/**
* Creator to enable deserialization of a FantaFlavorOneOf.
*
* @param val
* the value to use
* @return a new instance of {@link InnerFantaFlavorOneOf}.
*/
@com.fasterxml.jackson.annotation.JsonCreator
@Nonnull
static InnerFantaFlavorOneOf create( @Nonnull final FantaFlavorOneOf val )
{
return new InnerFantaFlavorOneOf(val);
}

/**
* Helper class to create a String that implements {@link FantaFlavor}.
*/
record InnerString(@com.fasterxml.jackson.annotation.JsonValue @Nonnull String value) implements FantaFlavor {}

/**
* Creator to enable deserialization of a String.
*
* @param val
* the value to use
* @return a new instance of {@link InnerString}.
*/
@com.fasterxml.jackson.annotation.JsonCreator
@Nonnull
static InnerString create( @Nonnull final String val )
{
return new InnerString(val);
}

}
Loading
Loading