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
73 changes: 73 additions & 0 deletions codegen/internal/generator/additional_properties_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,82 @@ func TestGenerateModelWithPropertiesAndAdditionalProperties(t *testing.T) {
assertContains(t, generated, "public Builder additionalProperty(String name, Object value)")
}

func TestGenerateModelWithoutBuilderForTypeAliases(t *testing.T) {
t.Parallel()

tmp := t.TempDir()
specPath := filepath.Join(tmp, "openapi.json")
outputDir := filepath.Join(tmp, "src", "main", "java")
resourceDir := filepath.Join(tmp, "src", "main", "resources")

spec := `{
"openapi": "3.0.3",
"info": {
"title": "test",
"version": "1.0.0"
},
"paths": {},
"components": {
"schemas": {
"Lon": {
"type": "number",
"format": "float"
},
"Meta": {
"type": "object"
}
}
}
}`
if err := os.WriteFile(specPath, []byte(spec), 0o644); err != nil {
t.Fatalf("write spec: %v", err)
}

params := Params{
SpecPath: specPath,
OutputDir: outputDir,
ResourceDir: resourceDir,
BasePackage: "com.test.sdk",
}
if err := Run(context.Background(), params); err != nil {
t.Fatalf("run generator: %v", err)
}

lonPath := filepath.Join(outputDir, "com", "test", "sdk", "models", "Lon.java")
lonContent, err := os.ReadFile(lonPath)
if err != nil {
t.Fatalf("read generated Lon model: %v", err)
}
lonGenerated := string(lonContent)

assertContains(t, lonGenerated, "public record Lon(")
assertContains(t, lonGenerated, "Float value")
assertNotContains(t, lonGenerated, "public static Builder builder()")
assertNotContains(t, lonGenerated, "public static final class Builder")

metaPath := filepath.Join(outputDir, "com", "test", "sdk", "models", "Meta.java")
metaContent, err := os.ReadFile(metaPath)
if err != nil {
t.Fatalf("read generated Meta model: %v", err)
}
metaGenerated := string(metaContent)

assertContains(t, metaGenerated, "public record Meta(")
assertContains(t, metaGenerated, "java.util.Map<String, Object> value")
assertNotContains(t, metaGenerated, "public static Builder builder()")
assertNotContains(t, metaGenerated, "public static final class Builder")
}

func assertContains(t *testing.T, content, want string) {
t.Helper()
if !strings.Contains(content, want) {
t.Fatalf("expected generated output to contain %q", want)
}
}

func assertNotContains(t *testing.T, content, want string) {
t.Helper()
if strings.Contains(content, want) {
t.Fatalf("expected generated output to not contain %q", want)
}
}
15 changes: 14 additions & 1 deletion codegen/internal/generator/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type schemaModel struct {
AdditionalProps *additionalPropertiesModel
Imports []string
HasRequired bool
HasBuilder bool
IsEnum bool
EnumValues []enumValueModel
}
Expand Down Expand Up @@ -547,7 +548,8 @@ func buildSchemas(doc *v3.Document, params Params, resolver *typeResolver) []sch
if additionalProps != nil {
imports = withAdditionalPropertiesImports(imports)
}
if hasRequired {
hasBuilder := shouldGenerateBuilder(fields, additionalProps)
if hasRequired && hasBuilder {
imports = uniqueStrings(append(imports, "java.util.Objects"))
}
model := schemaModel{
Expand All @@ -559,12 +561,23 @@ func buildSchemas(doc *v3.Document, params Params, resolver *typeResolver) []sch
AdditionalProps: additionalProps,
Imports: imports,
HasRequired: hasRequired,
HasBuilder: hasBuilder,
}
result = append(result, model)
}
return result
}

// shouldGenerateBuilder reports whether the model should expose a builder.
// Single-field wrapper records (for example Lon/Lat/Meta-style aliases) don't
// benefit from a builder and should use the canonical record constructor.
func shouldGenerateBuilder(fields []schemaField, additionalProps *additionalPropertiesModel) bool {
if additionalProps != nil {
return true
}
return !(len(fields) == 1 && fields[0].Name == "value")
}

// buildSchemaFields inspects a schema proxy and returns the fields, required
// imports, and a flag indicating whether any required properties exist.
func buildSchemaFields(name string, ref *base.SchemaProxy, resolver *typeResolver) ([]schemaField, *additionalPropertiesModel, []string, bool) {
Expand Down
1 change: 1 addition & 0 deletions codegen/internal/generator/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ func prepareModelTemplateData(schema schemaModel) map[string]any {
"Fields": schema.Fields,
"AdditionalProps": schema.AdditionalProps,
"HasRequired": schema.HasRequired,
"HasBuilder": schema.HasBuilder,
"IsEnum": schema.IsEnum,
"EnumValues": schema.EnumValues,
}
Expand Down
2 changes: 2 additions & 0 deletions codegen/internal/generator/templates/model.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public record {{ .ClassName }}(
}

{{- end }}
{{- if .HasBuilder }}
/**
* Creates a builder for {{ .ClassName }}.
*
Expand Down Expand Up @@ -164,5 +165,6 @@ public record {{ .ClassName }}(
{{- end }}
}
}
{{- end }}
}
{{- end }}
4 changes: 3 additions & 1 deletion codegen/internal/generator/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,8 @@ func (r *typeResolver) inlineSchemaModels(params Params) []schemaModel {
if additionalProps != nil {
imports = withAdditionalPropertiesImports(imports)
}
if hasRequired {
hasBuilder := shouldGenerateBuilder(fields, additionalProps)
if hasRequired && hasBuilder {
imports = uniqueStrings(append(imports, "java.util.Objects"))
}
models = append(models, schemaModel{
Expand All @@ -361,6 +362,7 @@ func (r *typeResolver) inlineSchemaModels(params Params) []schemaModel {
AdditionalProps: additionalProps,
Imports: imports,
HasRequired: hasRequired,
HasBuilder: hasBuilder,
})
info.processed = true
added = true
Expand Down
38 changes: 1 addition & 37 deletions src/main/java/com/sumup/sdk/models/Attributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,4 @@
package com.sumup.sdk.models;

/** Object attributes that are modifiable only by SumUp applications. */
public record Attributes(java.util.Map<String, Object> value) {
/**
* Creates a builder for Attributes.
*
* @return Builder that constructs immutable Attributes instances.
*/
public static Builder builder() {
return new Builder();
}

/** Builder for Attributes instances. */
public static final class Builder {
private java.util.Map<String, Object> value;

private Builder() {}

/**
* Sets the value for {@code value}.
*
* @param value Value for the value field.
* @return This builder instance.
*/
public Builder value(java.util.Map<String, Object> value) {
this.value = value;
return this;
}

/**
* Builds an immutable Attributes instance.
*
* @return Immutable Attributes.
*/
public Attributes build() {
return new Attributes(value);
}
}
}
public record Attributes(java.util.Map<String, Object> value) {}
38 changes: 1 addition & 37 deletions src/main/java/com/sumup/sdk/models/BusinessOwners.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,4 @@
package com.sumup.sdk.models;

/** Business owners information. */
public record BusinessOwners(java.util.List<com.sumup.sdk.models.BusinessOwnersItem> value) {
/**
* Creates a builder for BusinessOwners.
*
* @return Builder that constructs immutable BusinessOwners instances.
*/
public static Builder builder() {
return new Builder();
}

/** Builder for BusinessOwners instances. */
public static final class Builder {
private java.util.List<com.sumup.sdk.models.BusinessOwnersItem> value;

private Builder() {}

/**
* Sets the value for {@code value}.
*
* @param value Value for the value field.
* @return This builder instance.
*/
public Builder value(java.util.List<com.sumup.sdk.models.BusinessOwnersItem> value) {
this.value = value;
return this;
}

/**
* Builds an immutable BusinessOwners instance.
*
* @return Immutable BusinessOwners.
*/
public BusinessOwners build() {
return new BusinessOwners(value);
}
}
}
public record BusinessOwners(java.util.List<com.sumup.sdk.models.BusinessOwnersItem> value) {}
38 changes: 1 addition & 37 deletions src/main/java/com/sumup/sdk/models/ChangeStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,4 @@
* have been applied, the status `done`. The status is only returned after write operations or on
* read endpoints when the `version` query parameter is provided.
*/
public record ChangeStatus(String value) {
/**
* Creates a builder for ChangeStatus.
*
* @return Builder that constructs immutable ChangeStatus instances.
*/
public static Builder builder() {
return new Builder();
}

/** Builder for ChangeStatus instances. */
public static final class Builder {
private String value;

private Builder() {}

/**
* Sets the value for {@code value}.
*
* @param value Value for the value field.
* @return This builder instance.
*/
public Builder value(String value) {
this.value = value;
return this;
}

/**
* Builds an immutable ChangeStatus instance.
*
* @return Immutable ChangeStatus.
*/
public ChangeStatus build() {
return new ChangeStatus(value);
}
}
}
public record ChangeStatus(String value) {}
38 changes: 1 addition & 37 deletions src/main/java/com/sumup/sdk/models/CheckoutSuccess.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,4 @@
// Code generated by sumup-java/codegen. DO NOT EDIT.
package com.sumup.sdk.models;

public record CheckoutSuccess(com.sumup.sdk.models.Checkout value) {
/**
* Creates a builder for CheckoutSuccess.
*
* @return Builder that constructs immutable CheckoutSuccess instances.
*/
public static Builder builder() {
return new Builder();
}

/** Builder for CheckoutSuccess instances. */
public static final class Builder {
private com.sumup.sdk.models.Checkout value;

private Builder() {}

/**
* Sets the value for {@code value}.
*
* @param value Value for the value field.
* @return This builder instance.
*/
public Builder value(com.sumup.sdk.models.Checkout value) {
this.value = value;
return this;
}

/**
* Builds an immutable CheckoutSuccess instance.
*
* @return Immutable CheckoutSuccess.
*/
public CheckoutSuccess build() {
return new CheckoutSuccess(value);
}
}
}
public record CheckoutSuccess(com.sumup.sdk.models.Checkout value) {}
38 changes: 1 addition & 37 deletions src/main/java/com/sumup/sdk/models/CompanyIdentifiers.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,4 @@
package com.sumup.sdk.models;

/** A list of country-specific company identifiers. */
public record CompanyIdentifiers(java.util.List<com.sumup.sdk.models.CompanyIdentifier> value) {
/**
* Creates a builder for CompanyIdentifiers.
*
* @return Builder that constructs immutable CompanyIdentifiers instances.
*/
public static Builder builder() {
return new Builder();
}

/** Builder for CompanyIdentifiers instances. */
public static final class Builder {
private java.util.List<com.sumup.sdk.models.CompanyIdentifier> value;

private Builder() {}

/**
* Sets the value for {@code value}.
*
* @param value Value for the value field.
* @return This builder instance.
*/
public Builder value(java.util.List<com.sumup.sdk.models.CompanyIdentifier> value) {
this.value = value;
return this;
}

/**
* Builds an immutable CompanyIdentifiers instance.
*
* @return Immutable CompanyIdentifiers.
*/
public CompanyIdentifiers build() {
return new CompanyIdentifiers(value);
}
}
}
public record CompanyIdentifiers(java.util.List<com.sumup.sdk.models.CompanyIdentifier> value) {}
Loading
Loading