From d0375be35345d6b0f2ebd85bd77650464adc1ea4 Mon Sep 17 00:00:00 2001 From: Austin Ziegler Date: Thu, 20 Jun 2024 22:50:38 -0400 Subject: [PATCH] Add support for static type overrides with imports This allows static type overrides to be provided on the generator command-line, optionally with imports. This has been added specifically to override the use of `float64` for `xsd:decimal`. For our current need we only need to swap the handled type from `float64` to `string`: ```console $ ./gocomply_xsd2go convert XSD NAMESPACE DESTINATION \ --type-override decimal=string ``` For the `catalog.xsd` (which also requires the `xml.xsd`) from https://salesforcecommercecloud.github.io/b2c-dev-doc/docs/current/xsd/, this generates the following partial diff: ```diff diff --git i/catalog/models.go w/catalog/models.go index e0be71998af5..80d355eb279d 100644 --- i/catalog/models.go +++ w/catalog/models.go @@ -150,17 +150,17 @@ type Product struct { Upc *SimpleTypeGenericString256 `xml:"upc"` Unit *SimpleTypeGenericString256 `xml:"unit"` - UnitQuantity *float64 `xml:"unit-quantity"` + UnitQuantity string `xml:"unit-quantity"` UnitMeasure *SimpleTypeGenericString60 `xml:"unit-measure"` - MinOrderQuantity *float64 `xml:"min-order-quantity"` + MinOrderQuantity string `xml:"min-order-quantity"` - StepQuantity *float64 `xml:"step-quantity"` + StepQuantity string `xml:"step-quantity"` DisplayName []SharedTypeLocalizedString `xml:"display-name"` ShortDescription []SharedTypeLocalizedText `xml:"short-description"` ``` If we needed to keep it usable for math, but support fixed point decimal values, we could use `github.com/ericlagergren/decimal`: ```console $ ./gocomply_xsd2go convert XSD NAMESPACE DESTINATION \ --type-override decimal=decimal:github.com/ericlagergren/decimal ``` This produces the following partial diff: ```diff diff --git i/catalog/models.go w/catalog/models.go index e0be71998af5..f3d574061389 100644 --- i/catalog/models.go +++ w/catalog/models.go @@ -2,10 +2,11 @@ // Models for http://www.demandware.com/xml/impex/catalog/2006-10-31 package catalog import ( "encoding/xml" + "github.com/ericlagergren/decimal" ) // Element type Catalog struct { XMLName xml.Name `xml:"catalog"` @@ -150,17 +151,17 @@ type Product struct { Upc *SimpleTypeGenericString256 `xml:"upc"` Unit *SimpleTypeGenericString256 `xml:"unit"` - UnitQuantity *float64 `xml:"unit-quantity"` + UnitQuantity *decimal `xml:"unit-quantity"` UnitMeasure *SimpleTypeGenericString60 `xml:"unit-measure"` - MinOrderQuantity *float64 `xml:"min-order-quantity"` + MinOrderQuantity *decimal `xml:"min-order-quantity"` - StepQuantity *float64 `xml:"step-quantity"` + StepQuantity *decimal `xml:"step-quantity"` DisplayName []SharedTypeLocalizedString `xml:"display-name"` ShortDescription []SharedTypeLocalizedText `xml:"short-description"` ``` There are no constraints on ensuring that the XSD static type currently exists, so this *could* potentially be useful for providing temporary implementations for values like `xsd:duration`, but it is not clear to me whether this is the case. --- cli/cmd/cmd.go | 23 +++++++++++++++++++++++ pkg/xsd/schema.go | 10 +++++----- pkg/xsd/types.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/cli/cmd/cmd.go b/cli/cmd/cmd.go index 506af8e..45f2bc6 100644 --- a/cli/cmd/cmd.go +++ b/cli/cmd/cmd.go @@ -5,6 +5,7 @@ import ( "os" "strings" + "github.com/gocomply/xsd2go/pkg/xsd" "github.com/gocomply/xsd2go/pkg/xsd2go" "github.com/urfave/cli" ) @@ -37,10 +38,28 @@ var convert = cli.Command{ 1) } } + + for _, override := range c.StringSlice("type-override") { + if !strings.Contains(override, "=") { + return cli.NewExitError( + fmt.Sprintf( + "Invalid type-override: '%s', expecting form of TYPE=GOTYPE or TYPE=GOTYPE:GOIMPORT", + override, + ), + 1, + ) + } + } + return nil }, Action: func(c *cli.Context) error { xsdFile, goModule, outputDir := c.Args()[0], c.Args()[1], c.Args()[2] + + for _, typeOverride := range c.StringSlice("type-override") { + xsd.AddStaticTypeOverride(typeOverride) + } + err := xsd2go.Convert(xsdFile, goModule, outputDir, c.StringSlice("xmlns-override")) if err != nil { return cli.NewExitError(err, 1) @@ -52,5 +71,9 @@ var convert = cli.Command{ Name: "xmlns-override", Usage: "Allows to explicitly set gopackage name for given XMLNS. Example: --xmlns-override='http://www.w3.org/2000/09/xmldsig#=xml_signatures'", }, + cli.StringSliceFlag{ + Name: "type-override", + Usage: "Allows to explicitly override a static simple type mapping. Example: --type-override='decimal=string' or --type-override='decimal=decimal:github.com/ericlagergren/decimal", + }, }, } diff --git a/pkg/xsd/schema.go b/pkg/xsd/schema.go index 4799aac..4b6e1c3 100644 --- a/pkg/xsd/schema.go +++ b/pkg/xsd/schema.go @@ -84,7 +84,6 @@ func (sch *Schema) findReferencedElement(ref reference) *Element { } if innerSchema != sch { sch.registerImportedModule(innerSchema) - } return innerSchema.GetElement(ref.Name()) } @@ -257,6 +256,9 @@ func (sch *Schema) GoImportsNeeded() []string { for _, importedMod := range sch.importedModules { imports = append(imports, fmt.Sprintf("%s/%s", sch.ModulesPath, importedMod.GoPackageName())) } + for _, importedMod := range GetStaticTypeImports() { + imports = append(imports, importedMod) + } sort.Strings(imports) return imports } @@ -297,8 +299,7 @@ type Import struct { func (i *Import) load(ws *Workspace, baseDir string) (err error) { if i.SchemaLocation != "" { - i.ImportedSchema, err = - ws.loadXsd(filepath.Join(baseDir, i.SchemaLocation), true) + i.ImportedSchema, err = ws.loadXsd(filepath.Join(baseDir, i.SchemaLocation), true) } return } @@ -312,8 +313,7 @@ type Include struct { func (i *Include) load(ws *Workspace, baseDir string) (err error) { if i.SchemaLocation != "" { - i.IncludedSchema, err = - ws.loadXsd(filepath.Join(baseDir, i.SchemaLocation), false) + i.IncludedSchema, err = ws.loadXsd(filepath.Join(baseDir, i.SchemaLocation), false) } return } diff --git a/pkg/xsd/types.go b/pkg/xsd/types.go index df1b575..6197745 100644 --- a/pkg/xsd/types.go +++ b/pkg/xsd/types.go @@ -2,6 +2,8 @@ package xsd import ( "encoding/xml" + "sort" + "strings" "github.com/iancoleman/strcase" ) @@ -285,9 +287,43 @@ var staticTypes = map[string]staticType{ "byte": "int8", } +var ( + staticTypeImports = map[string]string{} + staticTypeUsed = map[string]struct{}{} +) + +func AddStaticTypeOverride(override string) { + parts := strings.SplitN(override, "=", 2) + typeParts := strings.SplitN(parts[1], ":", 2) + + typeName := parts[0] + + staticTypes[typeName] = staticType(typeParts[0]) + + if len(typeParts) == 2 { + staticTypeImports[typeName] = typeParts[1] + } +} + +func GetStaticTypeImports() []string { + imports := []string{} + + for name, mod := range staticTypeImports { + if _, found := staticTypeUsed[name]; found { + imports = append(imports, mod) + } + } + + sort.Strings(imports) + + return imports +} + func StaticType(name string) staticType { typ, found := staticTypes[name] if found { + staticTypeUsed[name] = struct{}{} + return typ } panic("Type xsd:" + name + " not implemented")