diff --git a/cmd/generate-fix/internal/template_helpers.go b/cmd/generate-fix/internal/template_helpers.go index f2c201b82..41758c70b 100644 --- a/cmd/generate-fix/internal/template_helpers.go +++ b/cmd/generate-fix/internal/template_helpers.go @@ -199,91 +199,42 @@ func quickfixValueType(quickfixType string) (goType string, err error) { } 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 "LOCALMKTTIME", "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 "XID", "XIDREF": - fallthrough - case "STRING": - quickfixType = "FIXString" - - case "BOOLEAN": - quickfixType = "FIXBoolean" - - case "LENGTH": - fallthrough - case "DAYOFMONTH": - fallthrough - case "NUMINGROUP": - fallthrough - case "SEQNUM": - fallthrough - case "TAGNUM": - 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": + // Define mappings of FIX field types to QuickFIX types + stringTypes := map[string]bool{ + "MULTIPLESTRINGVALUE": true, "MULTIPLEVALUESTRING": true, "MULTIPLECHARVALUE": true, + "CHAR": true, "CURRENCY": true, "DATA": true, "MONTHYEAR": true, + "LOCALMKTTIME": true, "LOCALMKTDATE": true, "TIME": true, "DATE": true, + "EXCHANGE": true, "LANGUAGE": true, "XMLDATA": true, "COUNTRY": true, + "UTCTIMEONLY": true, "UTCDATE": true, "UTCDATEONLY": true, "TZTIMEONLY": true, + "TZTIMESTAMP": true, "XID": true, "XIDREF": true, "STRING": true, + } + intTypes := map[string]bool{ + "LENGTH": true, "DAYOFMONTH": true, "NUMINGROUP": true, + "SEQNUM": true, "TAGNUM": true, "INT": true, + } + + floatTypes := map[string]bool{ + "QTY": true, "QUANTITY": true, "AMT": true, + "PRICE": true, "PRICEOFFSET": true, "PERCENTAGE": true, "FLOAT": true, + } + + switch { + case stringTypes[field.Type]: + return "FIXString", nil + case intTypes[field.Type]: + return "FIXInt", nil + case field.Type == "BOOLEAN": + return "FIXBoolean", nil + case field.Type == "UTCTIMESTAMP": + return "FIXUTCTimestamp", nil + case floatTypes[field.Type]: if *useFloat { - quickfixType = "FIXFloat" - } else { - quickfixType = "FIXDecimal" + return "FIXFloat", nil } - + return "FIXDecimal", nil default: - err = fmt.Errorf("Unknown type '%v' for tag '%v'\n", field.Type, field.Tag()) + return "", fmt.Errorf("Unknown type '%v' for tag '%v'\n", field.Type, field.Tag()) } - - return } func requiredFields(m *datadictionary.MessageDef) (required []*datadictionary.FieldDef) { diff --git a/validation.go b/validation.go index e9b718138..408943a87 100644 --- a/validation.go +++ b/validation.go @@ -364,11 +364,14 @@ func validateField(d *datadictionary.DataDictionary, _ datadictionary.TagSet, field TagValue, ) MessageRejectError { + // If the field has no value, return an error if len(field.value) == 0 { return TagSpecifiedWithoutAValue(field.tag) } fieldType, isMessageField := getFieldType(d, int(field.tag)) + + // If the field is neither a message field nor explicitly allowed, return an error if !isMessageField && !checkFieldNotDefined(settings, field.tag) { return InvalidTagNumber(field.tag) } @@ -377,80 +380,46 @@ func validateField(d *datadictionary.DataDictionary, return nil } + // Validate against allowed enumerations allowedValues := d.FieldTypeByTag[int(field.tag)].Enums if len(allowedValues) != 0 { if _, validValue := allowedValues[string(field.value)]; !validValue { return ValueIsIncorrect(field.tag) } } + // Define field type mappings for easy lookup + fieldTypeMapping := map[string]FieldValue{ + "MULTIPLESTRINGVALUE": new(FIXString), "MULTIPLEVALUESTRING": new(FIXString), + "MULTIPLECHARVALUE": new(FIXString), "CHAR": new(FIXString), + "CURRENCY": new(FIXString), "DATA": new(FIXString), + "MONTHYEAR": new(FIXString), "LOCALMKTDATE": new(FIXString), + "DATE": new(FIXString), "EXCHANGE": new(FIXString), + "LANGUAGE": new(FIXString), "XMLDATA": new(FIXString), + "COUNTRY": new(FIXString), "UTCTIMEONLY": new(FIXString), + "UTCDATEONLY": new(FIXString), "UTCDATE": new(FIXString), + "TZTIMEONLY": new(FIXString), "TZTIMESTAMP": new(FIXString), + "STRING": new(FIXString), + + "BOOLEAN": new(FIXBoolean), - var prototype FieldValue - switch fieldType.Type { - case "MULTIPLESTRINGVALUE", "MULTIPLEVALUESTRING": - fallthrough - case "MULTIPLECHARVALUE": - fallthrough - case "CHAR": - fallthrough - case "CURRENCY": - fallthrough - case "DATA": - fallthrough - case "MONTHYEAR": - fallthrough - case "LOCALMKTDATE", "DATE": - fallthrough - case "EXCHANGE": - fallthrough - case "LANGUAGE": - fallthrough - case "XMLDATA": - fallthrough - case "COUNTRY": - fallthrough - case "UTCTIMEONLY": - fallthrough - case "UTCDATEONLY", "UTCDATE": - fallthrough - case "TZTIMEONLY": - fallthrough - case "TZTIMESTAMP": - fallthrough - case "STRING": - prototype = new(FIXString) - - case "BOOLEAN": - prototype = new(FIXBoolean) - - case "LENGTH": - fallthrough - case "DAYOFMONTH": - fallthrough - case "NUMINGROUP": - fallthrough - case "SEQNUM": - fallthrough - case "INT": - prototype = new(FIXInt) - - case "UTCTIMESTAMP", "TIME": - prototype = new(FIXUTCTimestamp) - - case "QTY", "QUANTITY": - fallthrough - case "AMT": - fallthrough - case "PRICE": - fallthrough - case "PRICEOFFSET": - fallthrough - case "PERCENTAGE": - fallthrough - case "FLOAT": - prototype = new(FIXFloat) + "LENGTH": new(FIXInt), "DAYOFMONTH": new(FIXInt), + "NUMINGROUP": new(FIXInt), "SEQNUM": new(FIXInt), + "INT": new(FIXInt), + "UTCTIMESTAMP": new(FIXUTCTimestamp), "TIME": new(FIXUTCTimestamp), + + "QTY": new(FIXFloat), "QUANTITY": new(FIXFloat), + "AMT": new(FIXFloat), "PRICE": new(FIXFloat), + "PRICEOFFSET": new(FIXFloat), "PERCENTAGE": new(FIXFloat), + "FLOAT": new(FIXFloat), + } + // Get the appropriate prototype for field validation + prototype, exists := fieldTypeMapping[fieldType.Type] + if !exists { + return nil // If the field type is not recognized, no validation needed } + // Validate the field's value format if err := prototype.Read(field.value); err != nil { return IncorrectDataFormatForValue(field.tag) }