X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=document%2Fdocument.go;h=0c8b0f4a0a94d1219f70f2ddf5b8906572cb1c46;hb=34d06eb5c368465927c780c21d6deac1c7f847b8;hp=7e9896508c112de4a62c2bd995c82700718944e6;hpb=293e53e15524518b254091a155c5d04f4305816d;p=epoint diff --git a/document/document.go b/document/document.go index 7e98965..0c8b0f4 100644 --- a/document/document.go +++ b/document/document.go @@ -143,61 +143,31 @@ type Notice struct { } type Cert struct { - IsDebit bool Holder string Serial int64 Balance int64 Denomination string Issuer string Date int64 - Difference int64 - Draft string - Beneficiary *string // only in debit cert - Drawer *string // only in credit cert - DebitCert *string // only in credit cert AuthorizedBy string Notes *string // optional LastDebitSerial int64 // 0 if none LastCreditSerial int64 // 0 if none LastCert *string // nil if serial == 1 References []string + Difference int64 + Draft string } type DebitCert struct { - Holder string - Serial int64 - Balance int64 - Denomination string - Issuer string - Date int64 - Difference int64 - Draft string + Cert Beneficiary string - AuthorizedBy string - Notes *string // optional - LastDebitSerial int64 // 0 if none - LastCreditSerial int64 // 0 if none - LastCert *string // nil if serial == 1 - References []string } type CreditCert struct { - Holder string - Serial int64 - Balance int64 - Denomination string - Issuer string - Date int64 - Difference int64 - Draft string + Cert Drawer string DebitCert string - AuthorizedBy string - Notes *string // optional - LastDebitSerial int64 // 0 if none - LastCreditSerial int64 // 0 if none - LastCert *string // ? if serial == 1 - References []string } type BounceCert struct { @@ -215,43 +185,9 @@ func ToCert(v interface{}) (cert *Cert, err error) { cert = new(Cert) switch x := v.(type) { case *DebitCert: - cert.IsDebit = true - cert.Beneficiary = &x.Beneficiary - - cert.Holder = x.Holder - cert.Serial = x.Serial - cert.Balance = x.Balance - cert.Denomination = x.Denomination - cert.Issuer = x.Issuer - cert.Date = x.Date - cert.Difference = x.Difference - cert.Draft = x.Draft - cert.AuthorizedBy = x.AuthorizedBy - cert.Notes = x.Notes - cert.LastDebitSerial = x.LastDebitSerial - cert.LastCreditSerial = x.LastCreditSerial - cert.LastCert = x.LastCert - cert.References = x.References - + cert = &x.Cert case *CreditCert: - cert.IsDebit = false - cert.Drawer = &x.Drawer - cert.DebitCert = &x.DebitCert - - cert.Holder = x.Holder - cert.Serial = x.Serial - cert.Balance = x.Balance - cert.Denomination = x.Denomination - cert.Issuer = x.Issuer - cert.Date = x.Date - cert.Difference = x.Difference - cert.Draft = x.Draft - cert.AuthorizedBy = x.AuthorizedBy - cert.Notes = x.Notes - cert.LastDebitSerial = x.LastDebitSerial - cert.LastCreditSerial = x.LastCreditSerial - cert.LastCert = x.LastCert - cert.References = x.References + cert = &x.Cert default: err = fmt.Errorf("ToCert: only debit or credit document can be converted to cert") } @@ -492,44 +428,29 @@ func FormatDocument(doc *Document) (body []byte, err error) { } // parse doc fields into a struct according to the document type -func ParseStruct(doc *Document) (iv interface{}, err error) { - switch doc.Type { - case "Draft": - iv = new(Draft) - case "Notice": - iv = new(Notice) - case "DebitCert": - iv = new(DebitCert) - case "CreditCert": - iv = new(CreditCert) - case "BounceCert": - iv = new(BounceCert) - default: - err = fmt.Errorf("ParseStruct: unkown doc type: %s", doc.Type) - return - } - seen := make(map[string]bool) - v := reflect.ValueOf(iv).Elem() +func parseStruct(v reflect.Value, fields map[string]string, seen map[string]bool) (err error) { t := v.Type() n := v.NumField() - nokey := 0 - for i := 0; i < n; i++ { + for i := 0; i < n && err == nil; i++ { ft := t.Field(i) fv := v.Field(i) + if ft.Anonymous && fv.Kind() == reflect.Struct { + err = parseStruct(fv, fields, seen) + continue + } key := fieldname[ft.Name] if key == "" { key = ft.Name } - seen[key] = true - s, ok := doc.Fields[key] + s, ok := fields[key] if !ok { if fv.Kind() == reflect.Ptr { // missing optional key: leave the pointer as nil - nokey++ continue } - return nil, fmt.Errorf("ParseStruct: field %s of %s is missing\n", key, t.Name()) + return fmt.Errorf("ParseStruct: field %s of %s is missing\n", key, t.Name()) } + seen[key] = true if fv.Kind() == reflect.Ptr { if s == "" || s == "-" { // TODO @@ -570,14 +491,35 @@ func ParseStruct(doc *Document) (iv interface{}, err error) { default: panic("bad field type " + key + " " + fieldtype[key]) } - if err != nil { - return - } } - if len(doc.Fields)+nokey != n { - for k := range doc.Fields { - if !seen[k] { - err = fmt.Errorf("ParseStruct: unknown field %s in %s", k, t.Name()) + return +} + +func ParseStruct(doc *Document) (iv interface{}, err error) { + switch doc.Type { + case "Draft": + iv = new(Draft) + case "Notice": + iv = new(Notice) + case "DebitCert": + iv = new(DebitCert) + case "CreditCert": + iv = new(CreditCert) + case "BounceCert": + iv = new(BounceCert) + default: + err = fmt.Errorf("ParseStruct: unkown doc type: %s", doc.Type) + return + } + seen := make(map[string]bool) + err = parseStruct(reflect.ValueOf(iv).Elem(), doc.Fields, seen) + if err != nil { + return + } + if len(doc.Fields) != len(seen) { + for f := range doc.Fields { + if !seen[f] { + err = fmt.Errorf("ParseStruct: unknown field %s in %s", f, doc.Type) return } } @@ -586,20 +528,19 @@ func ParseStruct(doc *Document) (iv interface{}, err error) { } // turn a struct into a document -func FormatStruct(iv interface{}) (doc *Document, err error) { - v := reflect.ValueOf(iv) - if v.Kind() != reflect.Ptr || v.IsNil() || v.Elem().Kind() != reflect.Struct { - panic("input is not a pointer to struct") - } - v = v.Elem() +func formatStruct(v reflect.Value, doc *Document) (err error) { t := v.Type() n := v.NumField() - doc = new(Document) - doc.Type = t.Name() - doc.Fields = make(map[string]string) for i := 0; i < n; i++ { ft := t.Field(i) fv := v.Field(i) + if ft.Anonymous && fv.Kind() == reflect.Struct { + err = formatStruct(fv, doc) + if err != nil { + return + } + continue + } key := fieldname[ft.Name] if key == "" { key = ft.Name @@ -640,6 +581,19 @@ func FormatStruct(iv interface{}) (doc *Document, err error) { return } +// turn a struct into a document +func FormatStruct(iv interface{}) (doc *Document, err error) { + v := reflect.ValueOf(iv) + if v.Kind() != reflect.Ptr || v.IsNil() || v.Elem().Kind() != reflect.Struct { + panic("input is not a pointer to struct") + } + doc = new(Document) + doc.Type = v.Elem().Type().Name() + doc.Fields = make(map[string]string) + err = formatStruct(v.Elem(), doc) + return +} + func ParseFields(s []byte) (fields map[string]string, rest []byte, err error) { rest = s fields = make(map[string]string)