github.com/qiniu/go-sdk/v7@v7.27.0/internal/api-generator/form.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/dave/jennifer/jen"
     7  	"github.com/iancoleman/strcase"
     8  )
     9  
    10  type (
    11  	FormUrlencodedRequestStruct struct {
    12  		Fields []FormUrlencodedRequestField `yaml:"fields,omitempty"`
    13  	}
    14  
    15  	FormUrlencodedRequestField struct {
    16  		FieldName          string             `yaml:"field_name,omitempty"`
    17  		FieldCamelCaseName string             `yaml:"field_camel_case_name,omitempty"`
    18  		FieldSnakeCaseName string             `yaml:"field_snake_case_name,omitempty"`
    19  		Key                string             `yaml:"key,omitempty"`
    20  		Documentation      string             `yaml:"documentation,omitempty"`
    21  		Type               *StringLikeType    `yaml:"type,omitempty"`
    22  		Multiple           bool               `yaml:"multiple,omitempty"`
    23  		Optional           *OptionalType      `yaml:"optional,omitempty"`
    24  		ServiceBucket      *ServiceBucketType `yaml:"service_bucket,omitempty"`
    25  		ServiceObject      *ServiceObjectType `yaml:"service_object,omitempty"`
    26  	}
    27  )
    28  
    29  func (field *FormUrlencodedRequestField) camelCaseName() string {
    30  	if field.FieldCamelCaseName != "" {
    31  		return field.FieldCamelCaseName
    32  	}
    33  	return strcase.ToCamel(field.FieldName)
    34  }
    35  
    36  func (form *FormUrlencodedRequestStruct) addFields(group *jen.Group) error {
    37  	for _, field := range form.Fields {
    38  		if err := form.generateField(group, field); err != nil {
    39  			return err
    40  		}
    41  	}
    42  	return nil
    43  }
    44  
    45  func (form *FormUrlencodedRequestStruct) addGetBucketNameFunc(group *jen.Group, structName string) (bool, error) {
    46  	field := form.getServiceBucketField()
    47  	if field == nil || field.ServiceBucket.ToServiceBucketType() == ServiceBucketTypeNone {
    48  		return false, nil
    49  	} else if field.Multiple {
    50  		panic(fmt.Sprintf("multiple service bucket fields: %s", field.FieldName))
    51  	} else if t := field.Type.ToStringLikeType(); t != StringLikeTypeString {
    52  		panic(fmt.Sprintf("service bucket field must be string: %s", t))
    53  	}
    54  	group.Add(jen.Func().
    55  		Params(jen.Id("form").Op("*").Id(structName)).
    56  		Id("getBucketName").
    57  		Params(jen.Id("ctx").Qual("context", "Context")).
    58  		Params(jen.String(), jen.Error()).
    59  		BlockFunc(func(group *jen.Group) {
    60  			fieldName := field.camelCaseName()
    61  			switch field.ServiceBucket.ToServiceBucketType() {
    62  			case ServiceBucketTypePlainText:
    63  				group.Add(jen.Return(jen.Id("form").Dot(fieldName), jen.Nil()))
    64  			case ServiceBucketTypeEntry:
    65  				group.Add(
    66  					jen.Return(
    67  						jen.Qual("strings", "SplitN").
    68  							Call(jen.Id("form").Dot(fieldName), jen.Lit(":"), jen.Lit(2)).
    69  							Index(jen.Lit(0)),
    70  						jen.Nil(),
    71  					),
    72  				)
    73  			case ServiceBucketTypeUploadToken:
    74  				group.Add(
    75  					jen.If(jen.Id("putPolicy"), jen.Err()).
    76  						Op(":=").
    77  						Qual(PackageNameUpToken, "NewParser").
    78  						Call(jen.Id("form").Dot(fieldName)).
    79  						Dot("GetPutPolicy").
    80  						Call(jen.Id("ctx")).
    81  						Op(";").
    82  						Err().
    83  						Op("!=").
    84  						Nil().
    85  						BlockFunc(func(group *jen.Group) {
    86  							group.Add(jen.Return(jen.Lit(""), jen.Err()))
    87  						}).
    88  						Else().
    89  						BlockFunc(func(group *jen.Group) {
    90  							group.Add(jen.Return(jen.Id("putPolicy").Dot("GetBucketName").Call()))
    91  						}),
    92  				)
    93  			default:
    94  				panic("unknown ServiceBucketType")
    95  			}
    96  		}))
    97  	return true, nil
    98  }
    99  
   100  func (form *FormUrlencodedRequestStruct) addGetObjectNameFunc(group *jen.Group, structName string) (bool, error) {
   101  	field := form.getServiceObjectField()
   102  	if field == nil || field.ServiceObject.ToServiceObjectType() == ServiceObjectTypeNone {
   103  		return false, nil
   104  	} else if field.Multiple {
   105  		panic(fmt.Sprintf("multiple service object fields: %s", field.FieldName))
   106  	} else if t := field.Type.ToStringLikeType(); t != StringLikeTypeString {
   107  		panic(fmt.Sprintf("service object field must be string: %s", t))
   108  	}
   109  	group.Add(jen.Func().
   110  		Params(jen.Id("form").Op("*").Id(structName)).
   111  		Id("getObjectName").
   112  		Params().
   113  		Params(jen.String()).
   114  		BlockFunc(func(group *jen.Group) {
   115  			fieldName := field.camelCaseName()
   116  			switch field.ServiceObject.ToServiceObjectType() {
   117  			case ServiceObjectTypePlainText:
   118  				if field.Optional.ToOptionalType() == OptionalTypeNullable {
   119  					group.Add(jen.Var().Id("objectName").String())
   120  					group.Add(jen.If(jen.Id("form").Dot(fieldName).Op("!=").Nil()).BlockFunc(func(group *jen.Group) {
   121  						group.Add(jen.Id("objectName").Op("=").Op("*").Id("form").Dot(fieldName))
   122  					}))
   123  					group.Add(jen.Return(jen.Id("objectName")))
   124  				} else {
   125  					group.Return(jen.Id("form").Dot(fieldName))
   126  				}
   127  			case ServiceObjectTypeEntry:
   128  				group.Add(
   129  					jen.Id("parts").
   130  						Op(":=").
   131  						Qual("strings", "SplitN").
   132  						Call(jen.Id("form").Dot(fieldName), jen.Lit(":"), jen.Lit(2)))
   133  				group.Add(jen.If(jen.Len(jen.Id("parts")).Op(">").Lit(1)), jen.BlockFunc(func(group *jen.Group) {
   134  					group.Return(jen.Id("parts").Index(jen.Lit(1)))
   135  				}))
   136  				group.Add(jen.Return(jen.Lit("")))
   137  			default:
   138  				panic("unknown ServiceObjectType")
   139  			}
   140  		}))
   141  	return true, nil
   142  }
   143  
   144  func (form *FormUrlencodedRequestStruct) addBuildFunc(group *jen.Group, structName string) error {
   145  	var finalErr error = nil
   146  	group.Add(
   147  		jen.Func().
   148  			Params(jen.Id("form").Op("*").Id(structName)).
   149  			Id("build").
   150  			Params().
   151  			Params(jen.Qual("net/url", "Values"), jen.Error()).
   152  			BlockFunc(func(group *jen.Group) {
   153  				group.Add(jen.Id("formValues").Op(":=").Make(jen.Qual("net/url", "Values")))
   154  				for _, field := range form.Fields {
   155  					if err := form.addSetCall(group, field, "form", "formValues"); err != nil {
   156  						finalErr = err
   157  						return
   158  					}
   159  				}
   160  				group.Add(jen.Return(jen.Id("formValues"), jen.Nil()))
   161  			}),
   162  	)
   163  	return finalErr
   164  }
   165  
   166  func (form *FormUrlencodedRequestStruct) getServiceBucketField() *FormUrlencodedRequestField {
   167  	var serviceBucketField *FormUrlencodedRequestField
   168  
   169  	for i := range form.Fields {
   170  		if form.Fields[i].ServiceBucket.ToServiceBucketType() != ServiceBucketTypeNone {
   171  			if serviceBucketField == nil {
   172  				serviceBucketField = &form.Fields[i]
   173  			} else {
   174  				panic(fmt.Sprintf("multiple service bucket fields: %s & %s", form.Fields[i].FieldName, serviceBucketField.FieldName))
   175  			}
   176  		}
   177  	}
   178  	return serviceBucketField
   179  }
   180  
   181  func (form *FormUrlencodedRequestStruct) getServiceObjectField() *FormUrlencodedRequestField {
   182  	var serviceObjectField *FormUrlencodedRequestField
   183  
   184  	for i := range form.Fields {
   185  		if form.Fields[i].ServiceObject.ToServiceObjectType() != ServiceBucketTypeNone {
   186  			if serviceObjectField == nil {
   187  				serviceObjectField = &form.Fields[i]
   188  			} else {
   189  				panic(fmt.Sprintf("multiple service object fields: %s & %s", form.Fields[i].FieldName, serviceObjectField.FieldName))
   190  			}
   191  		}
   192  	}
   193  	return serviceObjectField
   194  }
   195  
   196  func (form *FormUrlencodedRequestStruct) generateField(group *jen.Group, field FormUrlencodedRequestField) error {
   197  	code := jen.Id(field.camelCaseName())
   198  	if field.Multiple {
   199  		code = code.Index()
   200  	}
   201  	code, err := field.Type.AddTypeToStatement(code, field.Optional.ToOptionalType() == OptionalTypeNullable)
   202  	if err != nil {
   203  		return err
   204  	}
   205  	if field.Documentation != "" {
   206  		code = code.Comment(field.Documentation)
   207  	}
   208  	group.Add(code)
   209  	return nil
   210  }
   211  
   212  func (form *FormUrlencodedRequestStruct) addSetCall(group *jen.Group, field FormUrlencodedRequestField, formVarName, formValuesVarName string) error {
   213  	var (
   214  		code, valueConvertCode *jen.Statement
   215  		err                    error
   216  	)
   217  	fieldName := field.camelCaseName()
   218  	if field.Multiple {
   219  		valueConvertCode, err = field.Type.GenerateConvertCodeToString(jen.Id("value"))
   220  		if err != nil {
   221  			return err
   222  		}
   223  		code = jen.If(jen.Len(jen.Id(formVarName).Dot(fieldName)).Op(">").Lit(0)).
   224  			BlockFunc(func(group *jen.Group) {
   225  				group.Add(
   226  					jen.For(jen.List(jen.Id("_"), jen.Id("value")).Op(":=").Range().Add(jen.Id(formVarName).Dot(fieldName))).BlockFunc(func(group *jen.Group) {
   227  						group.Add(jen.Id(formValuesVarName).Dot("Add").Call(jen.Lit(field.Key), valueConvertCode))
   228  					}),
   229  				)
   230  			})
   231  	} else {
   232  		formField := jen.Id(formVarName).Dot(fieldName)
   233  		if field.Optional.ToOptionalType() == OptionalTypeNullable {
   234  			valueConvertCode, err = field.Type.GenerateConvertCodeToString(jen.Op("*").Add(formField))
   235  		} else {
   236  			valueConvertCode, err = field.Type.GenerateConvertCodeToString(formField)
   237  		}
   238  		if err != nil {
   239  			return err
   240  		}
   241  		zeroValue, err := field.Type.ZeroValue()
   242  		if err != nil {
   243  			return err
   244  		}
   245  		condition := formField.Clone()
   246  		if field.Optional.ToOptionalType() == OptionalTypeNullable {
   247  			condition = condition.Op("!=").Nil()
   248  		} else if v, ok := zeroValue.(bool); !ok || v {
   249  			condition = condition.Op("!=").Lit(zeroValue)
   250  		}
   251  		switch field.Optional.ToOptionalType() {
   252  		case OptionalTypeOmitEmpty, OptionalTypeRequired, OptionalTypeNullable:
   253  			code = jen.If(condition).BlockFunc(func(group *jen.Group) {
   254  				group.Add(jen.Id(formValuesVarName).Dot("Set").Call(jen.Lit(field.Key), valueConvertCode))
   255  			})
   256  		case OptionalTypeKeepEmpty:
   257  			code = jen.Id(formValuesVarName).Dot("Set").Call(jen.Lit(field.Key), valueConvertCode)
   258  		}
   259  	}
   260  	if field.Optional.ToOptionalType() == OptionalTypeRequired {
   261  		code = code.Else().BlockFunc(func(group *jen.Group) {
   262  			group.Add(jen.Return(
   263  				jen.Nil(),
   264  				jen.Qual(PackageNameErrors, "MissingRequiredFieldError").
   265  					ValuesFunc(func(group *jen.Group) {
   266  						group.Add(jen.Id("Name").Op(":").Lit(field.camelCaseName()))
   267  					}),
   268  			))
   269  		})
   270  	}
   271  	group.Add(code)
   272  	return nil
   273  }