Created
October 28, 2019 11:39
-
-
Save ZhangYet/66d570db101fdd01ad8f25d724215925 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package generator | |
import ( | |
"bytes" | |
"flag" | |
"fmt" | |
"go/format" | |
"html/template" | |
"strings" | |
"github.com/quickfixgo/quickfix" | |
"github.com/quickfixgo/quickfix/datadictionary" | |
) | |
var useFloat = flag.Bool("use-float", true, "By default, FIX float fields are represented as arbitrary-precision fixed-point decimal numbers. Set to 'true' to instead generate FIX float fields as float64 values.") | |
var CreateMessage = ` | |
func Create{{.Protocol}}{{.MsgName}}Message() *Message { | |
msg := NewMessage() | |
{{- range .HeaderFields }} | |
{{- if (eq .FieldType "FIXString") }} | |
msg.Header.SetField({{.Tag}}, {{.FieldType}}("{{.FieldValue}}")) | |
{{- else if (eq .FieldType "FIXUTCTimestamp") }} | |
msg.Header.SetField({{.Tag}}, FIXUTCTimestamp{time.Now(), true}) | |
{{- else}} | |
msg.Header.SetField({{.Tag}}, {{.FieldType}}({{.FieldValue}})) | |
{{- end}} | |
{{- end}} | |
{{println}} | |
{{- range .BodyFields }} | |
{{- if (eq .FieldType "FIXString") }} | |
msg.Body.SetField({{.Tag}}, {{.FieldType}}("{{.FieldValue}}")) | |
{{- else if (eq .FieldType "FIXUTCTimestamp") }} | |
msg.Body.SetField({{.Tag}}, FIXUTCTimestamp{time.Now(), true}) | |
{{- else}} | |
msg.Body.SetField({{.Tag}}, {{.FieldType}}({{.FieldValue}})) | |
{{- end}} | |
{{- end}} | |
{{println}} | |
{{- range .TrailerFields }} | |
{{- if (eq .FieldType "FIXString") }} | |
msg.Trailer.SetField({{.Tag}}, {{.FieldType}}("{{.FieldValue}}")) | |
{{- else if (eq .FieldType "FIXUTCTimestamp") }} | |
msg.Trailer.SetField({{.Tag}}, FIXUTCTimestamp{time.Now(), true}) | |
{{- else}} | |
msg.Trailer.SetField({{.Tag}}, {{.FieldType}}({{.FieldValue}})) | |
{{- end}} | |
{{- end}} | |
return msg | |
} | |
` | |
var NewMassageTmpl = template.Must(template.New("NewMessage").Parse(CreateMessage)) | |
type msgField struct { | |
Tag string | |
FieldType string | |
FieldValue string | |
} | |
type FixMsgTmplStruct struct { | |
Protocol string | |
MsgName string | |
HeaderFields []msgField | |
BodyFields []msgField | |
TrailerFields []msgField | |
} | |
func GenCode(msg *quickfix.Message, dict *datadictionary.DataDictionary) (string, error) { | |
msgName, err := msg.MsgType() | |
if err != nil { | |
return "", err | |
} | |
protocal, err := msg.Header.GetString(quickfix.Tag(8)) | |
if err != nil { | |
return "", err | |
} | |
fixMsg := FixMsgTmplStruct{ | |
Protocol: strings.Replace(protocal, ".", "", -1), | |
MsgName: string(msgName), | |
HeaderFields: make([]msgField, 0), | |
BodyFields: make([]msgField, 0), | |
TrailerFields: make([]msgField, 0), | |
} | |
for _, tag := range msg.Header.Tags() { | |
mf, err := genMsgField(tag, msg.Header.FieldMap, dict) | |
if err != nil { | |
return "", err | |
} | |
fixMsg.HeaderFields = append(fixMsg.HeaderFields, mf) | |
} | |
for _, tag := range msg.Body.Tags() { | |
mf, err := genMsgField(tag, msg.Body.FieldMap, dict) | |
if err != nil { | |
return "", err | |
} | |
fixMsg.BodyFields = append(fixMsg.BodyFields, mf) | |
} | |
for _, tag := range msg.Trailer.Tags() { | |
mf, err := genMsgField(tag, msg.Trailer.FieldMap, dict) | |
if err != nil { | |
return "", err | |
} | |
fixMsg.TrailerFields = append(fixMsg.TrailerFields, mf) | |
} | |
code, genCodeErr := genCode(fixMsg) | |
if genCodeErr != nil { | |
return "", genCodeErr | |
} | |
formattedCodeByte, formatErr := format.Source([]byte(code)) | |
if formatErr != nil { | |
fmt.Printf("format error: %v\n", formatErr) | |
return code, nil | |
} | |
return string(formattedCodeByte), nil | |
} | |
func genCode(data FixMsgTmplStruct) (string, error) { | |
buffer := new(bytes.Buffer) | |
if err := NewMassageTmpl.Execute(buffer, data); err != nil { | |
return "", err | |
} | |
return buffer.String(), nil | |
} | |
func genMsgField(tag quickfix.Tag, fieldMap quickfix.FieldMap, dict *datadictionary.DataDictionary) (msgField, error) { | |
mf := msgField{ | |
Tag: "", | |
} | |
tagStr := fmt.Sprintf("Tag(%d)", tag) | |
fieldType, ok := dict.FieldTypeByTag[int(tag)] | |
if !ok { | |
return mf, fmt.Errorf("%d didn't exists", tag) | |
} | |
fieldTypeStr, err := quickfixType(fieldType) | |
if err != nil { | |
return mf, err | |
} | |
value, err := fieldMap.GetString(tag) | |
if err != nil { | |
return mf, err | |
} | |
mf = msgField{ | |
Tag: tagStr, | |
FieldType: fieldTypeStr, | |
FieldValue: value, | |
} | |
return mf, nil | |
} | |
func quickfixType(field *datadictionary.FieldType) (quickfixType string, err error) { | |
switch field.Type { | |
case "MULTIPLESTRINGVALUE", "MULTIPLEVALUESTRING": | |
fallthrough | |
case "MULTIPLECHARVALUE": | |
fallthrough | |
case "CHAR": | |
fallthrough | |
case "CURRENCY": | |
fallthrough | |
case "DATA": | |
fallthrough | |
case "MONTHYEAR": | |
fallthrough | |
case "LOCALMKTDATE": | |
fallthrough | |
case "TIME": | |
fallthrough | |
case "DATE": | |
fallthrough | |
case "EXCHANGE": | |
fallthrough | |
case "LANGUAGE": | |
fallthrough | |
case "XMLDATA": | |
fallthrough | |
case "COUNTRY": | |
fallthrough | |
case "UTCTIMEONLY": | |
fallthrough | |
case "UTCDATE": | |
fallthrough | |
case "UTCDATEONLY": | |
fallthrough | |
case "TZTIMEONLY": | |
fallthrough | |
case "TZTIMESTAMP": | |
fallthrough | |
case "STRING": | |
quickfixType = "FIXString" | |
case "BOOLEAN": | |
quickfixType = "FIXBoolean" | |
case "LENGTH": | |
fallthrough | |
case "DAYOFMONTH": | |
fallthrough | |
case "NUMINGROUP": | |
fallthrough | |
case "SEQNUM": | |
fallthrough | |
case "INT": | |
quickfixType = "FIXInt" | |
case "UTCTIMESTAMP": | |
quickfixType = "FIXUTCTimestamp" | |
case "QTY": | |
fallthrough | |
case "QUANTITY": | |
fallthrough | |
case "AMT": | |
fallthrough | |
case "PRICE": | |
fallthrough | |
case "PRICEOFFSET": | |
fallthrough | |
case "PERCENTAGE": | |
fallthrough | |
case "FLOAT": | |
if *useFloat { | |
quickfixType = "FIXFloat" | |
} else { | |
quickfixType = "FIXDecimal" | |
} | |
default: | |
err = fmt.Errorf("Unknown type '%v' for tag '%v'\n", field.Type, field.Tag()) | |
} | |
return | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment