456 lines
14 KiB
Go
456 lines
14 KiB
Go
package internal
|
|
|
|
import (
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
var (
|
|
HeaderTemplate *template.Template
|
|
TrailerTemplate *template.Template
|
|
MessageTemplate *template.Template
|
|
TagTemplate *template.Template
|
|
FieldTemplate *template.Template
|
|
EnumTemplate *template.Template
|
|
)
|
|
|
|
func init() {
|
|
tmplFuncs := template.FuncMap{
|
|
"toLower": strings.ToLower,
|
|
"requiredFields": requiredFields,
|
|
"beginString": beginString,
|
|
"routerBeginString": routerBeginString,
|
|
"importRootPath": getImportPathRoot,
|
|
"quickfixType": quickfixType,
|
|
"quickfixValueType": quickfixValueType,
|
|
"getGlobalFieldType": getGlobalFieldType,
|
|
"collectStandardImports": collectStandardImports,
|
|
"collectExtraImports": collectExtraImports,
|
|
"checkIfDecimalImportRequiredForFields": checkIfDecimalImportRequiredForFields,
|
|
"decimalImport": func() string {
|
|
if *useUDecimal {
|
|
return "github.com/quagmt/udecimal"
|
|
}
|
|
return "github.com/shopspring/decimal"
|
|
},
|
|
"checkIfTimeImportRequiredForFields": checkIfTimeImportRequiredForFields,
|
|
"checkIfEnumImportRequired": checkIfEnumImportRequired,
|
|
}
|
|
|
|
baseTemplate := template.Must(template.New("Base").Funcs(tmplFuncs).Parse(`
|
|
{{ define "receiver" }}RECEIVER{{ end }}
|
|
|
|
{{ define "fieldsetter" -}}
|
|
{{- $field_type := getGlobalFieldType . -}}
|
|
{{- $qfix_type := quickfixType $field_type -}}
|
|
{{- if and ($field_type.Enums) (ne $qfix_type "FIXBoolean") -}}
|
|
Set{{ .Name }}(v enum.{{ .Name }}) {
|
|
{{ template "receiver" }}.Set(field.New{{ .Name }}(v))
|
|
}
|
|
{{- else if eq $qfix_type "FIXDecimal" -}}
|
|
Set{{ .Name }}(value decimal.Decimal, scale int32) {
|
|
{{ template "receiver" }}.Set(field.New{{ .Name }}(value, scale))
|
|
}
|
|
{{- else if eq $qfix_type "FIXUDecimal" -}}
|
|
Set{{ .Name }}(value udecimal.Decimal, scale uint8) {
|
|
{{ template "receiver" }}.Set(field.New{{ .Name }}(value, scale))
|
|
}
|
|
{{- else -}}
|
|
Set{{ .Name }}(v {{ quickfixValueType $qfix_type }}) {
|
|
{{ template "receiver" }}.Set(field.New{{ .Name }}(v))
|
|
}
|
|
{{- end }}{{ end }}
|
|
|
|
{{ define "groupsetter" -}}
|
|
Set{{ .Name }}(f {{ .Name }}RepeatingGroup){
|
|
{{ template "receiver" }}.SetGroup(f)
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "setters" }}
|
|
{{ range .Fields }}
|
|
// Set{{ .Name }} sets {{ .Name }}, Tag {{ .Tag }}.
|
|
func ({{ template "receiver" }} {{ $.Name }}) {{ if .IsGroup }}{{ template "groupsetter" . }}{{ else }}{{ template "fieldsetter" . }}{{ end }}
|
|
{{ end }}{{ end }}
|
|
|
|
{{ define "fieldgetter" -}}
|
|
Get{{ .Name }}() (f field.{{ .Name }}Field, err quickfix.MessageRejectError) {
|
|
err = {{ template "receiver" }}.Get(&f)
|
|
return
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "fieldvaluegetter" -}}
|
|
{{- $ft := getGlobalFieldType . -}}
|
|
{{- $bt := quickfixType $ft -}}
|
|
{{- if and $ft.Enums (ne $bt "FIXBoolean") -}}
|
|
Get{{ .Name }}() (v enum.{{ .Name }}, err quickfix.MessageRejectError) {
|
|
{{- else if eq $bt "FIXDecimal" -}}
|
|
Get{{ .Name }}() (v decimal.Decimal, err quickfix.MessageRejectError) {
|
|
{{- else if eq $bt "FIXUDecimal" -}}
|
|
Get{{ .Name }}() (v udecimal.Decimal, err quickfix.MessageRejectError) {
|
|
{{- else -}}
|
|
Get{{ .Name }}() (v {{ quickfixValueType $bt }}, err quickfix.MessageRejectError) {
|
|
{{- end }}
|
|
var f field.{{ .Name }}Field
|
|
if err = {{ template "receiver" }}.Get(&f); err == nil {
|
|
v = f.Value()
|
|
}
|
|
return
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "groupgetter" -}}
|
|
Get{{ .Name }}() ({{ .Name }}RepeatingGroup, quickfix.MessageRejectError) {
|
|
f := New{{ .Name }}RepeatingGroup()
|
|
err := {{ template "receiver" }}.GetGroup(f)
|
|
return f, err
|
|
}
|
|
{{- end }}
|
|
|
|
|
|
{{ define "getters" }}
|
|
{{ range .Fields }}
|
|
// Get{{ .Name }} gets {{ .Name }}, Tag {{ .Tag }}.
|
|
func ({{ template "receiver" }} {{ $.Name }}) {{if .IsGroup}}{{ template "groupgetter" . }}{{ else }}{{ template "fieldvaluegetter" .}}{{ end }}
|
|
{{ end }}{{ end }}
|
|
|
|
{{ define "hasers" }}
|
|
{{range .Fields}}
|
|
// Has{{ .Name}} returns true if {{ .Name}} is present, Tag {{ .Tag}}.
|
|
func ({{ template "receiver" }} {{ $.Name }}) Has{{ .Name}}() bool {
|
|
return {{ template "receiver" }}.Has(tag.{{ .Name}})
|
|
}
|
|
{{end}}{{ end }}
|
|
|
|
{{ define "group_template" }}
|
|
quickfix.GroupTemplate{
|
|
{{- range $index, $field := . }}
|
|
{{- if $field.IsGroup }}
|
|
New{{ $field.Name }}RepeatingGroup(),
|
|
{{- else}}
|
|
quickfix.GroupElement(tag.{{$field.Name}}),
|
|
{{- end }}
|
|
{{- end }}
|
|
}
|
|
{{- end }}
|
|
|
|
{{ define "field_args" }}
|
|
{{- range $index, $field := . }}{{if $index}},{{end}}{{toLower $field.Name}} field.{{ .Name }}Field{{ end }}
|
|
{{- end }}
|
|
|
|
{{ define "groups" }}
|
|
{{ range .Fields }}
|
|
{{ if .IsGroup }}
|
|
// {{ .Name }} is a repeating group element, Tag {{ .Tag }}.
|
|
type {{ .Name }} struct {
|
|
*quickfix.Group
|
|
}
|
|
|
|
{{ template "setters" .}}
|
|
{{ template "getters" . }}
|
|
{{ template "hasers" . }}
|
|
{{ template "groups" . }}
|
|
|
|
// {{ .Name }}RepeatingGroup is a repeating group, Tag {{ .Tag }}.
|
|
type {{ .Name }}RepeatingGroup struct {
|
|
*quickfix.RepeatingGroup
|
|
}
|
|
|
|
// New{{ .Name }}RepeatingGroup returns an initialized, {{ .Name }}RepeatingGroup.
|
|
func New{{ .Name }}RepeatingGroup() {{ .Name }}RepeatingGroup {
|
|
return {{ .Name }}RepeatingGroup{
|
|
quickfix.NewRepeatingGroup(
|
|
tag.{{ .Name }},
|
|
{{- template "group_template" .Fields }},
|
|
),
|
|
}
|
|
}
|
|
|
|
// Add create and append a new {{ .Name }} to this group.
|
|
func ({{ template "receiver" }} {{ .Name }}RepeatingGroup) Add() {{ .Name }} {
|
|
g := {{ template "receiver" }}.RepeatingGroup.Add()
|
|
return {{ .Name }}{g}
|
|
}
|
|
|
|
// Get returns the ith {{ .Name }} in the {{ .Name }}RepeatinGroup.
|
|
func ({{ template "receiver" }} {{ .Name}}RepeatingGroup) Get(i int) {{ .Name }} {
|
|
return {{ .Name }}{ {{ template "receiver" }}.RepeatingGroup.Get(i) }
|
|
}
|
|
|
|
{{ end }}{{ end }}{{ end }}
|
|
`))
|
|
|
|
HeaderTemplate = template.Must(template.Must(baseTemplate.Clone()).Parse(`
|
|
{{ define "receiver" }}h{{ end }}
|
|
// Code generated by quickfix. DO NOT EDIT.
|
|
package {{ .Package }}
|
|
|
|
import (
|
|
{{- if collectStandardImports .MessageDef }}
|
|
{{- range collectStandardImports .MessageDef }}
|
|
"{{ . }}"
|
|
{{- end }}{{ "\n" }}
|
|
{{- end }}
|
|
{{- if collectExtraImports .MessageDef }}
|
|
{{- range collectExtraImports .MessageDef }}
|
|
"{{ . }}"
|
|
{{- end }}{{ "\n" }}
|
|
{{- end }}
|
|
"quantex.com/qfixdpl/quickfix"
|
|
{{- if checkIfEnumImportRequired .MessageDef}}
|
|
"{{ importRootPath }}/enum"
|
|
{{- end }}
|
|
"{{ importRootPath }}/field"
|
|
"{{ importRootPath }}/tag"
|
|
)
|
|
|
|
// Header is the {{ .Package }} Header type.
|
|
type Header struct {
|
|
*quickfix.Header
|
|
}
|
|
|
|
// NewHeader returns a new, initialized Header instance.
|
|
func NewHeader(header *quickfix.Header) (h Header) {
|
|
h.Header = header
|
|
h.SetBeginString("{{ beginString .FIXSpec }}")
|
|
return
|
|
}
|
|
|
|
{{ template "setters" .}}
|
|
{{ template "getters" . }}
|
|
{{ template "hasers" . }}
|
|
{{ template "groups" . }}
|
|
`))
|
|
|
|
TrailerTemplate = template.Must(template.Must(baseTemplate.Clone()).Parse(`
|
|
{{ define "receiver" }}t{{ end }}
|
|
// Code generated by quickfix. DO NOT EDIT.
|
|
package {{ .Package }}
|
|
|
|
import (
|
|
{{- if collectStandardImports .MessageDef }}
|
|
{{- range collectStandardImports .MessageDef }}
|
|
"{{ . }}"
|
|
{{- end }}{{ "\n" }}
|
|
{{- end }}
|
|
{{- if collectExtraImports .MessageDef }}
|
|
{{- range collectExtraImports .MessageDef }}
|
|
"{{ . }}"
|
|
{{- end }}{{ "\n" }}
|
|
{{- end }}
|
|
"quantex.com/qfixdpl/quickfix"
|
|
{{- if checkIfEnumImportRequired .MessageDef}}
|
|
"{{ importRootPath }}/enum"
|
|
{{- end }}
|
|
"{{ importRootPath }}/field"
|
|
"{{ importRootPath }}/tag"
|
|
)
|
|
|
|
// Trailer is the {{ .Package }} Trailer type.
|
|
type Trailer struct {
|
|
*quickfix.Trailer
|
|
}
|
|
|
|
{{ template "setters" .}}
|
|
{{ template "getters" . }}
|
|
{{ template "hasers" . }}
|
|
{{ template "groups" . }}
|
|
`))
|
|
|
|
MessageTemplate = template.Must(baseTemplate.Parse(`
|
|
{{ define "receiver" }}m{{ end }}
|
|
// Code generated by quickfix. DO NOT EDIT.
|
|
package {{ .Package }}
|
|
|
|
import (
|
|
{{- if collectStandardImports .MessageDef }}
|
|
{{- range collectStandardImports .MessageDef }}
|
|
"{{ . }}"
|
|
{{- end }}{{ "\n" }}
|
|
{{- end }}
|
|
{{- if collectExtraImports .MessageDef }}
|
|
{{- range collectExtraImports .MessageDef }}
|
|
"{{ . }}"
|
|
{{- end }}{{ "\n" }}
|
|
{{- end }}
|
|
"quantex.com/qfixdpl/quickfix"
|
|
{{- if checkIfEnumImportRequired .MessageDef}}
|
|
"{{ importRootPath }}/enum"
|
|
{{- end }}
|
|
"{{ importRootPath }}/field"
|
|
"{{ importRootPath }}/{{ .TransportPackage }}"
|
|
"{{ importRootPath }}/tag"
|
|
)
|
|
|
|
// {{ .Name }} is the {{ .FIXPackage }} {{ .Name }} type, MsgType = {{ .MsgType }}.
|
|
type {{ .Name }} struct {
|
|
{{ .TransportPackage }}.Header
|
|
*quickfix.Body
|
|
{{ .TransportPackage }}.Trailer
|
|
Message *quickfix.Message
|
|
}
|
|
|
|
// FromMessage creates a {{ .Name }} from a quickfix.Message instance.
|
|
func FromMessage(m *quickfix.Message) {{ .Name }} {
|
|
return {{ .Name }}{
|
|
Header: {{ .TransportPackage}}.Header{Header: &m.Header},
|
|
Body: &m.Body,
|
|
Trailer: {{ .TransportPackage}}.Trailer{Trailer: &m.Trailer},
|
|
Message: m,
|
|
}
|
|
}
|
|
|
|
// ToMessage returns a quickfix.Message instance.
|
|
func (m {{ .Name }}) ToMessage() *quickfix.Message {
|
|
return m.Message
|
|
}
|
|
|
|
{{ $required_fields := requiredFields .MessageDef -}}
|
|
// New returns a {{ .Name }} initialized with the required fields for {{ .Name }}.
|
|
func New({{template "field_args" $required_fields }}) (m {{ .Name }}) {
|
|
m.Message = quickfix.NewMessage()
|
|
m.Header = {{ .TransportPackage }}.NewHeader(&m.Message.Header)
|
|
m.Body = &m.Message.Body
|
|
m.Trailer.Trailer = &m.Message.Trailer
|
|
|
|
m.Header.Set(field.NewMsgType("{{ .MessageDef.MsgType }}"))
|
|
{{- range $required_fields }}
|
|
m.Set({{ toLower .Name }})
|
|
{{- end }}
|
|
|
|
return
|
|
}
|
|
|
|
// A RouteOut is the callback type that should be implemented for routing Message.
|
|
type RouteOut func(msg {{ .Name }}, sessionID quickfix.SessionID) quickfix.MessageRejectError
|
|
|
|
// Route returns the beginstring, message type, and MessageRoute for this Message type.
|
|
func Route(router RouteOut) (string, string, quickfix.MessageRoute) {
|
|
r:=func(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError {
|
|
return router(FromMessage(msg), sessionID)
|
|
}
|
|
return "{{ routerBeginString .FIXSpec }}", "{{ .MessageDef.MsgType }}", r
|
|
}
|
|
|
|
{{ template "setters" . }}
|
|
{{ template "getters" . }}
|
|
{{ template "hasers" . }}
|
|
{{ template "groups" . }}
|
|
`))
|
|
|
|
TagTemplate = template.Must(template.New("Tag").Parse(`
|
|
// Code generated by quickfix. DO NOT EDIT.
|
|
package tag
|
|
import "quantex.com/qfixdpl/quickfix"
|
|
|
|
const (
|
|
{{- range .}}
|
|
{{ .Name }} quickfix.Tag = {{ .Tag }}
|
|
{{- end }}
|
|
)
|
|
`))
|
|
|
|
FieldTemplate = template.Must(template.New("Field").Funcs(tmplFuncs).Parse(`
|
|
// Code generated by quickfix. DO NOT EDIT.
|
|
package field
|
|
import (
|
|
{{ if checkIfTimeImportRequiredForFields . }}"time"{{ end }}
|
|
|
|
{{ if checkIfDecimalImportRequiredForFields . }}"{{ decimalImport }}"{{ end }}
|
|
|
|
"quantex.com/qfixdpl/quickfix"
|
|
"{{ importRootPath }}/enum"
|
|
"{{ importRootPath }}/tag"
|
|
)
|
|
|
|
{{ range . }}
|
|
{{- $base_type := quickfixType . -}}
|
|
|
|
{{ if and .Enums (ne $base_type "FIXBoolean") }}
|
|
// {{ .Name }}Field is a enum.{{ .Name }} field.
|
|
type {{ .Name }}Field struct { quickfix.FIXString }
|
|
{{ else }}
|
|
// {{ .Name }}Field is a {{ .Type }} field.
|
|
type {{ .Name }}Field struct { quickfix.{{ $base_type }} }
|
|
{{ end }}
|
|
|
|
// Tag returns tag.{{ .Name }} ({{ .Tag }}).
|
|
func (f {{ .Name }}Field) Tag() quickfix.Tag { return tag.{{ .Name }} }
|
|
|
|
{{ if eq $base_type "FIXUTCTimestamp" }}
|
|
// New{{ .Name }} returns a new {{ .Name }}Field initialized with val.
|
|
func New{{ .Name }}(val time.Time) {{ .Name }}Field {
|
|
return New{{ .Name }}WithPrecision(val, quickfix.Millis)
|
|
}
|
|
|
|
// New{{ .Name }}NoMillis returns a new {{ .Name }}Field initialized with val without millisecs.
|
|
func New{{ .Name }}NoMillis(val time.Time) {{ .Name }}Field {
|
|
return New{{ .Name }}WithPrecision(val, quickfix.Seconds)
|
|
}
|
|
|
|
// New{{ .Name }}WithPrecision returns a new {{ .Name }}Field initialized with val of specified precision.
|
|
func New{{ .Name }}WithPrecision(val time.Time, precision quickfix.TimestampPrecision) {{ .Name }}Field {
|
|
return {{ .Name }}Field{ quickfix.FIXUTCTimestamp{ Time: val, Precision: precision } }
|
|
}
|
|
|
|
{{ else if and .Enums (ne $base_type "FIXBoolean") }}
|
|
func New{{ .Name }}(val enum.{{ .Name }}) {{ .Name }}Field {
|
|
return {{ .Name }}Field{ quickfix.FIXString(val) }
|
|
}
|
|
{{ else if eq $base_type "FIXDecimal" }}
|
|
// New{{ .Name }} returns a new {{ .Name }}Field initialized with val and scale.
|
|
func New{{ .Name }}(val decimal.Decimal, scale int32) {{ .Name }}Field {
|
|
return {{ .Name }}Field{ quickfix.FIXDecimal{ Decimal: val, Scale: scale} }
|
|
}
|
|
{{ else if eq $base_type "FIXUDecimal" }}
|
|
// New{{ .Name }} returns a new {{ .Name }}Field initialized with val and scale.
|
|
func New{{ .Name }}(val udecimal.Decimal, scale uint8) {{ .Name }}Field {
|
|
return {{ .Name }}Field{ quickfix.FIXUDecimal{ Decimal: val, Scale: scale} }
|
|
}
|
|
{{ else }}
|
|
// New{{ .Name }} returns a new {{ .Name }}Field initialized with val.
|
|
func New{{ .Name }}(val {{ quickfixValueType $base_type }}) {{ .Name }}Field {
|
|
return {{ .Name }}Field{ quickfix.{{ $base_type }}(val) }
|
|
}
|
|
{{ end }}
|
|
|
|
{{ if and .Enums (ne $base_type "FIXBoolean") }}
|
|
func (f {{ .Name }}Field) Value() enum.{{ .Name }} { return enum.{{ .Name }}(f.String()) }
|
|
{{ else if eq $base_type "FIXDecimal" }}
|
|
func (f {{ .Name }}Field) Value() (val decimal.Decimal) { return f.Decimal }
|
|
{{ else if eq $base_type "FIXUDecimal" }}
|
|
func (f {{ .Name }}Field) Value() (val udecimal.Decimal) { return f.Decimal }
|
|
{{ else }}
|
|
func (f {{ .Name }}Field) Value() ({{ quickfixValueType $base_type }}) {
|
|
{{- if eq $base_type "FIXString" -}}
|
|
return f.String() }
|
|
{{- else if eq $base_type "FIXBoolean" -}}
|
|
return f.Bool() }
|
|
{{- else if eq $base_type "FIXInt" -}}
|
|
return f.Int() }
|
|
{{- else if eq $base_type "FIXUTCTimestamp" -}}
|
|
return f.Time }
|
|
{{- else if eq $base_type "FIXFloat" -}}
|
|
return f.Float() }
|
|
{{- else -}}
|
|
TEMPLATE ERROR: Value() for {{ $base_type }}
|
|
{{ end }}{{ end }}{{ end }}
|
|
`))
|
|
|
|
EnumTemplate = template.Must(template.New("Enum").Parse(`
|
|
// Code generated by quickfix. DO NOT EDIT.
|
|
package enum
|
|
{{ range $ft := . }}
|
|
{{ if $ft.Enums }}
|
|
// {{ $ft.Name }} field enumeration values.
|
|
type {{ $ft.Name }} string
|
|
const(
|
|
{{ range $ft.Enums }}
|
|
{{ $ft.Name }}_{{ .Description }} {{ $ft.Name }} = "{{ .Value }}"
|
|
{{- end }}
|
|
)
|
|
{{ end }}{{ end }}
|
|
`))
|
|
}
|