From a27ffa48f9d939579a13c27b987c7068ae4f0ad2 Mon Sep 17 00:00:00 2001 From: Carlo Goetz Date: Fri, 12 Jun 2026 10:35:40 +0200 Subject: [PATCH] feat(go): patch iaas/AreaID after generation to fix oneOf regex issue STACKITSDK-226 --- CustomRegionGenerator.java | 198 +++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) diff --git a/CustomRegionGenerator.java b/CustomRegionGenerator.java index 160fda5..8b03089 100644 --- a/CustomRegionGenerator.java +++ b/CustomRegionGenerator.java @@ -5,6 +5,11 @@ import org.openapitools.codegen.CodegenParameter; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.security.MessageDigest; +import java.util.Arrays; import java.util.Set; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; @@ -68,4 +73,197 @@ private boolean isRegionField(String name) { } return name.equalsIgnoreCase("region") || name.equalsIgnoreCase("regionId"); } + private final byte[] IAAS_AREA_ID_HASH = {-73, 66, 84, 86, -60, 99, 59, 46, -116, 10, 97, -23, -85, 59, 87, -98}; + private final String IAAS_AREA_ID_PATCHED = """ +/* +STACKIT IaaS API + +This API allows you to create and modify IaaS resources. + +API version: 2 +Contact: stackit-iaas@mail.schwarz +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package v2api + +import ( + "encoding/json" + "fmt" + "regexp" +) + +// AreaId - The identifier (ID) of an area. +type AreaId struct { + StaticAreaID *StaticAreaID + String *string +} + +// StaticAreaIDAsAreaId is a convenience function that returns StaticAreaID wrapped in AreaId +func StaticAreaIDAsAreaId(v *StaticAreaID) AreaId { + return AreaId{ + StaticAreaID: v, + } +} + +// stringAsAreaId is a convenience function that returns string wrapped in AreaId +func StringAsAreaId(v *string) AreaId { + return AreaId{ + String: v, + } +} + +// Unmarshal JSON data into one of the pointers in the struct +func (dst *AreaId) UnmarshalJSON(data []byte) error { + var err error + match := 0 + // try to unmarshal data into StaticAreaID + err = json.Unmarshal(data, &dst.StaticAreaID) + if err == nil { + jsonStaticAreaID, _ := json.Marshal(dst.StaticAreaID) + if string(jsonStaticAreaID) == "{}" { // empty struct + dst.StaticAreaID = nil + } else { + match++ + } + } else { + dst.StaticAreaID = nil + } + + // try to unmarshal data into String + err = json.Unmarshal(data, &dst.String) + if err == nil { + jsonString, _ := json.Marshal(dst.String) + regex := `/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/` + regex = regexp.MustCompile("^\\\\/|\\\\/$").ReplaceAllString(regex, "$1") // Remove beginning slash and ending slash + regex = regexp.MustCompile("\\\\\\\\(.)").ReplaceAllString(regex, "$1") // Remove duplicate escaping char for dots + rawString := regexp.MustCompile(`^"|"$`).ReplaceAllString(*dstAreaId1.String, "$1") // Remove quotes + isMatched, _ := regexp.MatchString(regex, rawString) + if string(jsonString) != "{}" && isMatched { // empty struct + dst.String = nil + } else { + match++ + } + } else { + dst.String = nil + } + + if match > 1 { // more than 1 match + // reset to nil + dst.StaticAreaID = nil + dst.String = nil + + return fmt.Errorf("data matches more than one schema in oneOf(AreaId)") + } else if match == 1 { + return nil // exactly one match + } else { // no match + return fmt.Errorf("data failed to match schemas in oneOf(AreaId)") + } +} + +// Marshal data from the first non-nil pointers in the struct to JSON +func (src AreaId) MarshalJSON() ([]byte, error) { + if src.StaticAreaID != nil { + return json.Marshal(&src.StaticAreaID) + } + + if src.String != nil { + return json.Marshal(&src.String) + } + + return nil, nil // no data in oneOf schemas +} + +// Get the actual instance +func (obj *AreaId) GetActualInstance() interface{} { + if obj == nil { + return nil + } + if obj.StaticAreaID != nil { + return obj.StaticAreaID + } + + if obj.String != nil { + return obj.String + } + + // all schemas are nil + return nil +} + +// Get the actual instance value +func (obj AreaId) GetActualInstanceValue() interface{} { + if obj.StaticAreaID != nil { + return *obj.StaticAreaID + } + + if obj.String != nil { + return *obj.String + } + + // all schemas are nil + return nil +} + +type NullableAreaId struct { + value *AreaId + isSet bool +} + +func (v NullableAreaId) Get() *AreaId { + return v.value +} + +func (v *NullableAreaId) Set(val *AreaId) { + v.value = val + v.isSet = true +} + +func (v NullableAreaId) IsSet() bool { + return v.isSet +} + +func (v *NullableAreaId) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableAreaId(val *AreaId) *NullableAreaId { + return &NullableAreaId{value: val, isSet: true} +} + +func (v NullableAreaId) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableAreaId) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} +"""; + + @Override + public void postProcessFile(File file, String fileType) { + if (file.getAbsolutePath().endsWith("iaas/v2api/model_area_id.go")) { + try { + var content = Files.readAllBytes(file.toPath()); + var digest = MessageDigest.getInstance("MD5"); + var hash = digest.digest(content); + if (Arrays.equals(hash, IAAS_AREA_ID_HASH)) { + Files.writeString(file.toPath(), IAAS_AREA_ID_PATCHED, StandardOpenOption.TRUNCATE_EXISTING); + } else { + throw new IllegalStateException( + "expected iaas/v2api/model_area_id.go to hash to " + + Arrays.toString(IAAS_AREA_ID_HASH) + " but got " + Arrays.toString(hash) + + "\nedit CustomRegionGenerator.java in the sdk-generator and update IAAS_AREA_ID_HASH" + + "to accept this change" + ); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + super.postProcessFile(file, fileType); + } }