package encode // import "udico.de/uditaren/opier/encode" import ( "bytes" "fmt" "sort" "strconv" "strings" "udico.de/opier/openapi" ) type simpleparam struct { Name string Type string In string } // implement sort interface on simpleparam type simpleparamslice []*simpleparam func (s simpleparamslice) Len() int { return len(s) } func (s simpleparamslice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s simpleparamslice) Less(i, j int) bool { val := func(s string) int { switch s { case "path": return 0 case "head": return 1 case "query": return 2 } return 99 } iVal := val(s[i].In) jVal := val(s[j].In) iStr := s[i].Name jStr := s[j].Name if iVal == jVal { return strings.Compare(iStr, jStr) < 0 } return iVal < jVal } // Funcs generates all functions for a given tag // // tag is a // tag name func (e Encoder) Funcs(tag string, operations []*openapi.Operation) string { tBuf := bytes.Buffer{} tBuf.WriteString(fmt.Sprintf("package %v\n\n", e.Package)) tBuf.WriteString(e.GeneratedHeader()) tBuf.WriteString(e.tagType(tag)) tFuncPrefix := "p" + NormalizeName(tag) for _, op := range operations { // name -> type tParams := make([]*simpleparam, 0, 5) if op.Description != "" { tDesc := strings.Split(strings.TrimSpace(op.Description), "\n") for _, tLine := range tDesc { tBuf.WriteString(fmt.Sprintf("// %v\n", tLine)) } } for _, params := range op.Path().Parameters { tBuf.WriteString("// param [PATH] ") if params.Ref != "" { // ref param tRefParam := e.api.ResolveParameter(params.Ref) tBuf.WriteString(fmt.Sprintf("REF: %v\n", params.Ref)) tBuf.WriteString(Comment(tRefParam.Name, 2)) tParams = append(tParams, &simpleparam{ Name: tRefParam.Name, Type: tRefParam.Schema.GoType(), In: "path", }) } else { tBuf.WriteString(fmt.Sprintf("TYPE: %v\n", params.Schema.Type)) tParams = append(tParams, &simpleparam{ Name: params.Name, Type: params.Schema.GoType(), In: "path", }) } } for _, params := range op.Parameters { //tBuf.WriteString("// param ") tBuf.WriteString(Comment(fmt.Sprintf("param [%v] %v: %v\n", params.In, params.Name, params.Description), 0)) tParams = append(tParams, &simpleparam{ Name: params.Name, Type: params.Schema.GoType(), In: string(params.In), }) } if op.RequestBody != nil { tBuf.WriteString(fmt.Sprintf("// body: %v\n", op.RequestBody.Description)) for k, v := range op.RequestBody.Content { tBuf.WriteString(fmt.Sprintf("// [%v]: %v\n", k, v.Schema.Ref)) } } var tResponseType *openapi.ResponseObject = nil for tCode, tResponse := range op.Responses { tBuf.WriteString(Comment(fmt.Sprintf("response [%v]: %v\n", tCode, tResponse.Description), 0)) tCodeVal, _ := strconv.Atoi(tCode) if tCodeVal/100 == 2 { tResponseType = tResponse } } tResponses := make([]*simpleparam, 0, 2) if tResponseType != nil { for k, v := range tResponseType.Headers { // each given responseheader is a return parameter tResponses = append(tResponses, &simpleparam{ Name: k, Type: v.Schema.TypeOrReference(), In: "head", }) } if len(tResponseType.Content) > 0 { tSchema := tResponseType.Content["application/json"].Schema tResponses = append(tResponses, &simpleparam{ Name: "ret", Type: tSchema.GoType(), In: "body", }) } } sort.Sort(simpleparamslice(tParams)) sort.Sort(simpleparamslice(tResponses)) // parameter list: tResponses = append(tResponses, &simpleparam{ Name: "err", Type: "error", }) tParamBuf := &strings.Builder{} for i, tParam := range tParams { if i > 0 { tParamBuf.WriteString(", ") } tParamBuf.WriteString(NormalizeName(tParam.Name)) tParamBuf.WriteString(" " + tParam.Type) } // body parameter: if op.RequestBody != nil { ref := op.RequestBody.Content["application/json"].Schema.Ref if ref != "" { if tParamBuf.Len() > 0 { tParamBuf.WriteString(", ") } tParamBuf.WriteString(fmt.Sprintf("data *%v", e.api.ResolveSchema(ref).Name())) } else { tParamBuf.WriteString(" /* IMPLEMENT BODY SCHEMA which is not $ref */") } } tParamStr := tParamBuf.String() tResponseBuf := &strings.Builder{} tResponseBuf.WriteString("(") for i, tResponse := range tResponses { if i > 0 { tResponseBuf.WriteString(", ") } tResponseBuf.WriteString(tResponse.Name + " ") tResponseBuf.WriteString(tResponse.Type) } tResponseBuf.WriteString(")") tResponseStr := tResponseBuf.String() tBuf.WriteString(fmt.Sprintf("func (p %v) %v(%v) %v {\n", tFuncPrefix, NormalizeName(op.OperationId), tParamStr, tResponseStr)) // add header parameters // insert path parameters // add query parameters // post/put params ("body") tBuf.WriteString(fmt.Sprintf(" // [%v]%v operation here \n", op.Method(), op.Path().Name)) tBuf.WriteString(fmt.Sprintf(" return\n}\n\n")) } return tBuf.String() } func (e Encoder) tagType(tag string) string { tNorm := NormalizeName(tag) tBuf := bytes.Buffer{} tBuf.WriteString("import \"net/http\"\n\n") tBuf.WriteString(Comment(e.getTagDescription(tag), 0)) tBuf.WriteString(fmt.Sprintf("type p%v struct {\n", tNorm)) tBuf.WriteString(" client *http.Client\n") tBuf.WriteString(" base string\n") tBuf.WriteString("}\n\n") tBuf.WriteString(fmt.Sprintf("func %v(aClient *http.Client, aBase string) p%v {\n", NormalizeName("new-"+tag), tNorm)) tBuf.WriteString(fmt.Sprintf(" return p%v{\n", tNorm)) tBuf.WriteString(" client: aClient,\n") tBuf.WriteString(" base: aBase,\n") tBuf.WriteString(" }\n") tBuf.WriteString("}\n\n") return tBuf.String() } func (e Encoder) getTagDescription(tag string) string { for _, v := range e.api.Tags { if v.Name == tag { return v.Description } } return "" }