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

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