Skip to content

Commit

Permalink
Merge pull request hooklift#222 from w65536/datetime-refs-xml-interfaces
Browse files Browse the repository at this point in the history
Generate xml.Marshaler and xml.Unmarshaler interface implementations for date/time types
  • Loading branch information
c4milo authored Dec 3, 2021
2 parents 7325f68 + de4df29 commit d91c993
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 23 deletions.
6 changes: 6 additions & 0 deletions fixtures/test.wsdl
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@
</s:restriction>
</s:simpleType>
</s:element>
<!-- element of type dateTime -->
<s:element name="startDate" type="s:dateTime">
<s:annotation>
<s:documentation>The date and time when the process starts.</s:documentation>
</s:annotation>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="GetInfoSoapIn">
Expand Down
108 changes: 108 additions & 0 deletions gowsdl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"bytes"
"errors"
"fmt"
"go/ast"
"go/format"
"go/parser"
"go/printer"
Expand Down Expand Up @@ -146,6 +147,61 @@ func TestElementWithLocalSimpleType(t *testing.T) {
}
}

func TestDateTimeType(t *testing.T) {
g, err := NewGoWSDL("fixtures/test.wsdl", "myservice", false, true)
if err != nil {
t.Error(err)
}

resp, err := g.Start()
if err != nil {
t.Fatal(err)
}

// Type declaration
actual, err := getTypeDeclaration(resp, "StartDate")
if err != nil {
fmt.Println(string(resp["types"]))
t.Fatal(err)
}

expected := `type StartDate soap.XSDDateTime`

if actual != expected {
t.Error("got \n" + actual + " want \n" + expected)
}

// Method declaration MarshalXML
actual, err = getFuncDeclaration(resp, "MarshalXML", "StartDate")
if err != nil {
fmt.Println(string(resp["types"]))
t.Fatal(err)
}

expected = `func (xdt StartDate) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
return soap.XSDDateTime(xdt).MarshalXML(e, start)
}`

if actual != expected {
t.Error("got \n" + actual + " want \n" + expected)
}

// Method declaration UnmarshalXML
actual, err = getFuncDeclaration(resp, "UnmarshalXML", "StartDate")
if err != nil {
fmt.Println(string(resp["types"]))
t.Fatal(err)
}

expected = `func (xdt *StartDate) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return (*soap.XSDDateTime)(xdt).UnmarshalXML(d, start)
}`

if actual != expected {
t.Error("got \n" + actual + " want \n" + expected)
}
}

func TestVboxGeneratesWithoutSyntaxErrors(t *testing.T) {
files, err := filepath.Glob("fixtures/*.wsdl")
if err != nil {
Expand Down Expand Up @@ -288,3 +344,55 @@ func getTypeDeclaration(resp map[string][]byte, name string) (string, error) {
}
return buf.String(), nil
}

func findFuncDecl(f *ast.File, name string, recv string) *ast.Decl {
// Loop over all declarations
for _, decl := range f.Decls {
if funcDecl, ok := decl.(*ast.FuncDecl); ok {
// Found FuncDecl declaration type
if funcDecl.Name.Name == name {
// Found match with function name
if recvType, ok := funcDecl.Recv.List[0].Type.(*ast.Ident); ok {
// Value receiver type
if recvType.Name == recv {
// Found receiver type match
return &decl
}
} else if recvTypePtr, ok := funcDecl.Recv.List[0].Type.(*ast.StarExpr); ok {
// Pointer receiver type
if recvType, ok := recvTypePtr.X.(*ast.Ident); ok {
if recvType.Name == recv {
// Found receiver type match
return &decl
}
}
}
}
}
}

return nil
}

func getFuncDeclaration(resp map[string][]byte, name string, recv string) (string, error) {
source, err := format.Source([]byte(string(resp["header"]) + string(resp["types"])))
if err != nil {
return "", err
}
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "myservice.go", string(source), parser.DeclarationErrors)
if err != nil {
return "", err
}

decl := findFuncDecl(f, name, recv)
if decl == nil {
return "", errors.New("Function declaration " + name + " not found")
}
var buf bytes.Buffer
err = printer.Fprint(&buf, fset, *decl)
if err != nil {
return "", err
}
return buf.String(), nil
}
72 changes: 49 additions & 23 deletions types_tmpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,26 @@ package gowsdl

var typesTmpl = `
{{define "SimpleType"}}
{{$type := replaceReservedWords .Name | makePublic}}
{{$typeName := replaceReservedWords .Name | makePublic}}
{{if .Doc}} {{.Doc | comment}} {{end}}
{{if ne .List.ItemType ""}}
type {{$type}} []{{toGoType .List.ItemType false}}
type {{$typeName}} []{{toGoType .List.ItemType false}}
{{else if ne .Union.MemberTypes ""}}
type {{$type}} string
type {{$typeName}} string
{{else if .Union.SimpleType}}
type {{$type}} string
type {{$typeName}} string
{{else if .Restriction.Base}}
type {{$type}} {{toGoType .Restriction.Base false}}
type {{$typeName}} {{toGoType .Restriction.Base false}}
{{else}}
type {{$type}} interface{}
type {{$typeName}} interface{}
{{end}}
{{if .Restriction.Enumeration}}
const (
{{with .Restriction}}
{{range .Enumeration}}
{{if .Doc}} {{.Doc | comment}} {{end}}
{{$type}}{{$value := replaceReservedWords .Value}}{{$value | makePublic}} {{$type}} = "{{goString .Value}}" {{end}}
{{$typeName}}{{$value := replaceReservedWords .Value}}{{$value | makePublic}} {{$typeName}} = "{{goString .Value}}" {{end}}
{{end}}
)
{{end}}
Expand Down Expand Up @@ -116,10 +116,11 @@ var typesTmpl = `
{{range .Elements}}
{{$name := .Name}}
{{$typeName := replaceReservedWords $name | makePublic}}
{{if not .Type}}
{{/* ComplexTypeLocal */}}
{{with .ComplexType}}
type {{$name | replaceReservedWords | makePublic}} struct {
type {{$typeName}} struct {
XMLName xml.Name ` + "`xml:\"{{$targetNamespace}} {{$name}}\"`" + `
{{if ne .ComplexContent.Extension.Base ""}}
{{template "ComplexContent" .ComplexContent}}
Expand All @@ -137,47 +138,72 @@ var typesTmpl = `
{{end}}
{{/* SimpleTypeLocal */}}
{{with .SimpleType}}
{{$type := replaceReservedWords $name | makePublic}}
{{if .Doc}} {{.Doc | comment}} {{end}}
{{if ne .List.ItemType ""}}
type {{$type}} []{{toGoType .List.ItemType false}}
type {{$typeName}} []{{toGoType .List.ItemType false}}
{{else if ne .Union.MemberTypes ""}}
type {{$type}} string
type {{$typeName}} string
{{else if .Union.SimpleType}}
type {{$type}} string
type {{$typeName}} string
{{else if .Restriction.Base}}
type {{$type}} {{toGoType .Restriction.Base false}}
type {{$typeName}} {{toGoType .Restriction.Base false}}
{{else}}
type {{$type}} interface{}
type {{$typeName}} interface{}
{{end}}
{{if .Restriction.Enumeration}}
const (
{{with .Restriction}}
{{range .Enumeration}}
{{if .Doc}} {{.Doc | comment}} {{end}}
{{$type}}{{$value := replaceReservedWords .Value}}{{$value | makePublic}} {{$type}} = "{{goString .Value}}" {{end}}
{{$typeName}}{{$value := replaceReservedWords .Value}}{{$value | makePublic}} {{$typeName}} = "{{goString .Value}}" {{end}}
{{end}}
)
{{end}}
{{end}}
{{else}}
{{if ne ($name | replaceReservedWords | makePublic) (toGoType .Type .Nillable | removePointerFromType)}}
type {{$name | replaceReservedWords | makePublic}} {{toGoType .Type .Nillable | removePointerFromType}}
{{$type := toGoType .Type .Nillable | removePointerFromType}}
{{if ne ($typeName) ($type)}}
type {{$typeName}} {{$type}}
{{if eq ($type) ("soap.XSDDateTime")}}
func (xdt {{$typeName}}) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
return soap.XSDDateTime(xdt).MarshalXML(e, start)
}
func (xdt *{{$typeName}}) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return (*soap.XSDDateTime)(xdt).UnmarshalXML(d, start)
}
{{else if eq ($type) ("soap.XSDDate")}}
func (xd {{$typeName}}) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
return soap.XSDDate(xd).MarshalXML(e, start)
}
func (xd *{{$typeName}}) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return (*soap.XSDDate)(xd).UnmarshalXML(d, start)
}
{{else if eq ($type) ("soap.XSDTime")}}
func (xt {{$typeName}}) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
return soap.XSDTime(xt).MarshalXML(e, start)
}
func (xt *{{$typeName}}) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return (*soap.XSDTime)(xt).UnmarshalXML(d, start)
}
{{end}}
{{end}}
{{end}}
{{end}}
{{range .ComplexTypes}}
{{/* ComplexTypeGlobal */}}
{{$name := replaceReservedWords .Name | makePublic}}
{{$typeName := replaceReservedWords .Name | makePublic}}
{{if and (eq (len .SimpleContent.Extension.Attributes) 0) (eq (toGoType .SimpleContent.Extension.Base false) "string") }}
type {{$name}} string
type {{$typeName}} string
{{else}}
type {{$name}} struct {
{{$typ := findNameByType .Name}}
{{if ne $name $typ}}
XMLName xml.Name ` + "`xml:\"{{$targetNamespace}} {{$typ}}\"`" + `
type {{$typeName}} struct {
{{$type := findNameByType .Name}}
{{if ne $typeName $type}}
XMLName xml.Name ` + "`xml:\"{{$targetNamespace}} {{$type}}\"`" + `
{{end}}
{{if ne .ComplexContent.Extension.Base ""}}
Expand Down

0 comments on commit d91c993

Please sign in to comment.