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 }