github.com/anchorlabsinc/go-swagger@v0.19.0/generator/structs.go (about) 1 package generator 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "sort" 8 "strconv" 9 "strings" 10 11 "github.com/go-openapi/spec" 12 ) 13 14 // GenCommon contains common properties needed across 15 // definitions, app and operations 16 // TargetImportPath may be used by templates to import other (possibly 17 // generated) packages in the generation path (e.g. relative to GOPATH). 18 // TargetImportPath is NOT used by standard templates. 19 type GenCommon struct { 20 Copyright string 21 TargetImportPath string 22 } 23 24 // GenDefinition contains all the properties to generate a 25 // definition from a swagger spec 26 type GenDefinition struct { 27 GenCommon 28 GenSchema 29 Package string 30 Imports map[string]string 31 DefaultImports []string 32 ExtraSchemas GenSchemaList 33 DependsOn []string 34 External bool 35 } 36 37 // GenDefinitions represents a list of operations to generate 38 // this implements a sort by operation id 39 type GenDefinitions []GenDefinition 40 41 func (g GenDefinitions) Len() int { return len(g) } 42 func (g GenDefinitions) Less(i, j int) bool { return g[i].Name < g[j].Name } 43 func (g GenDefinitions) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 44 45 // GenSchemaList is a list of schemas for generation. 46 // 47 // It can be sorted by name to get a stable struct layout for 48 // version control and such 49 type GenSchemaList []GenSchema 50 51 // GenSchema contains all the information needed to generate the code 52 // for a schema 53 type GenSchema struct { 54 resolvedType 55 sharedValidations 56 Example string 57 OriginalName string 58 Name string 59 Suffix string 60 Path string 61 ValueExpression string 62 IndexVar string 63 KeyVar string 64 Title string 65 Description string 66 Location string 67 ReceiverName string 68 Items *GenSchema 69 AllowsAdditionalItems bool 70 HasAdditionalItems bool 71 AdditionalItems *GenSchema 72 Object *GenSchema 73 XMLName string 74 CustomTag string 75 Properties GenSchemaList 76 AllOf GenSchemaList 77 HasAdditionalProperties bool 78 IsAdditionalProperties bool 79 AdditionalProperties *GenSchema 80 ReadOnly bool 81 IsVirtual bool 82 IsBaseType bool 83 HasBaseType bool 84 IsSubType bool 85 IsExported bool 86 DiscriminatorField string 87 DiscriminatorValue string 88 Discriminates map[string]string 89 Parents []string 90 IncludeValidator bool 91 IncludeModel bool 92 Default interface{} 93 } 94 95 func (g GenSchemaList) Len() int { return len(g) } 96 func (g GenSchemaList) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 97 func (g GenSchemaList) Less(i, j int) bool { 98 a, okA := g[i].Extensions[xOrder].(float64) 99 b, okB := g[j].Extensions[xOrder].(float64) 100 101 // If both properties have x-order defined, then the one with lower x-order is smaller 102 if okA && okB { 103 return a < b 104 } 105 106 // If only the first property has x-order defined, then it is smaller 107 if okA { 108 return true 109 } 110 111 // If only the second property has x-order defined, then it is smaller 112 if okB { 113 return false 114 } 115 116 // If neither property has x-order defined, then the one with lower lexicographic name is smaller 117 return g[i].Name < g[j].Name 118 } 119 120 type sharedValidations struct { 121 HasValidations bool 122 Required bool 123 124 // String validations 125 MaxLength *int64 126 MinLength *int64 127 Pattern string 128 129 // Number validations 130 MultipleOf *float64 131 Minimum *float64 132 Maximum *float64 133 ExclusiveMinimum bool 134 ExclusiveMaximum bool 135 136 Enum []interface{} 137 ItemsEnum []interface{} 138 139 // Slice validations 140 MinItems *int64 141 MaxItems *int64 142 UniqueItems bool 143 HasSliceValidations bool 144 145 // Not used yet (perhaps intended for maxProperties, minProperties validations?) 146 NeedsSize bool 147 148 // NOTE: "patternProperties" and "dependencies" not supported by Swagger 2.0 149 } 150 151 // GenResponse represents a response object for code generation 152 type GenResponse struct { 153 Package string 154 ModelsPackage string 155 ReceiverName string 156 Name string 157 Description string 158 159 IsSuccess bool 160 161 Code int 162 Method string 163 Path string 164 Headers GenHeaders 165 Schema *GenSchema 166 AllowsForStreaming bool 167 168 Imports map[string]string 169 DefaultImports []string 170 171 Extensions map[string]interface{} 172 } 173 174 // GenHeader represents a header on a response for code generation 175 type GenHeader struct { 176 resolvedType 177 sharedValidations 178 179 Package string 180 ReceiverName string 181 IndexVar string 182 183 ID string 184 Name string 185 Path string 186 ValueExpression string 187 188 Title string 189 Description string 190 Default interface{} 191 HasDefault bool 192 193 CollectionFormat string 194 195 Child *GenItems 196 Parent *GenItems 197 198 Converter string 199 Formatter string 200 201 ZeroValue string 202 } 203 204 // ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array. 205 // For a header objects it always returns "". 206 func (g *GenHeader) ItemsDepth() string { 207 // NOTE: this is currently used by templates to generate explicit comments in nested structures 208 return "" 209 } 210 211 // GenHeaders is a sorted collection of headers for codegen 212 type GenHeaders []GenHeader 213 214 func (g GenHeaders) Len() int { return len(g) } 215 func (g GenHeaders) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 216 func (g GenHeaders) Less(i, j int) bool { return g[i].Name < g[j].Name } 217 218 // HasSomeDefaults returns true is at least one header has a default value set 219 func (g GenHeaders) HasSomeDefaults() bool { 220 // NOTE: this is currently used by templates to avoid empty constructs 221 for _, header := range g { 222 if header.HasDefault { 223 return true 224 } 225 } 226 return false 227 } 228 229 // GenParameter is used to represent 230 // a parameter or a header for code generation. 231 type GenParameter struct { 232 resolvedType 233 sharedValidations 234 235 ID string 236 Name string 237 ModelsPackage string 238 Path string 239 ValueExpression string 240 IndexVar string 241 KeyVar string 242 ReceiverName string 243 Location string 244 Title string 245 Description string 246 Converter string 247 Formatter string 248 249 Schema *GenSchema 250 251 CollectionFormat string 252 253 Child *GenItems 254 Parent *GenItems 255 256 /// Unused 257 //BodyParam *GenParameter 258 259 Default interface{} 260 HasDefault bool 261 ZeroValue string 262 AllowEmptyValue bool 263 264 // validation strategy for Body params, which may mix model and simple constructs. 265 // Distinguish the following cases: 266 // - HasSimpleBodyParams: body is an inline simple type 267 // - HasModelBodyParams: body is a model objectd 268 // - HasSimpleBodyItems: body is an inline array of simple type 269 // - HasModelBodyItems: body is an array of model objects 270 // - HasSimpleBodyMap: body is a map of simple objects (possibly arrays) 271 // - HasModelBodyMap: body is a map of model objects 272 HasSimpleBodyParams bool 273 HasModelBodyParams bool 274 HasSimpleBodyItems bool 275 HasModelBodyItems bool 276 HasSimpleBodyMap bool 277 HasModelBodyMap bool 278 279 Extensions map[string]interface{} 280 } 281 282 // IsQueryParam returns true when this parameter is a query param 283 func (g *GenParameter) IsQueryParam() bool { 284 return g.Location == "query" 285 } 286 287 // IsPathParam returns true when this parameter is a path param 288 func (g *GenParameter) IsPathParam() bool { 289 return g.Location == "path" 290 } 291 292 // IsFormParam returns true when this parameter is a form param 293 func (g *GenParameter) IsFormParam() bool { 294 return g.Location == "formData" 295 } 296 297 // IsHeaderParam returns true when this parameter is a header param 298 func (g *GenParameter) IsHeaderParam() bool { 299 return g.Location == "header" 300 } 301 302 // IsBodyParam returns true when this parameter is a body param 303 func (g *GenParameter) IsBodyParam() bool { 304 return g.Location == "body" 305 } 306 307 // IsFileParam returns true when this parameter is a file param 308 func (g *GenParameter) IsFileParam() bool { 309 return g.SwaggerType == "file" 310 } 311 312 // ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array. 313 // For a parameter object, it always returns "". 314 func (g *GenParameter) ItemsDepth() string { 315 // NOTE: this is currently used by templates to generate explicit comments in nested structures 316 return "" 317 } 318 319 // GenParameters represents a sorted parameter collection 320 type GenParameters []GenParameter 321 322 func (g GenParameters) Len() int { return len(g) } 323 func (g GenParameters) Less(i, j int) bool { return g[i].Name < g[j].Name } 324 func (g GenParameters) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 325 326 // HasSomeDefaults returns true is at least one parameter has a default value set 327 func (g GenParameters) HasSomeDefaults() bool { 328 // NOTE: this is currently used by templates to avoid empty constructs 329 for _, param := range g { 330 if param.HasDefault { 331 return true 332 } 333 } 334 return false 335 } 336 337 // GenItems represents the collection items for a collection parameter 338 type GenItems struct { 339 sharedValidations 340 resolvedType 341 342 Name string 343 Path string 344 ValueExpression string 345 CollectionFormat string 346 Child *GenItems 347 Parent *GenItems 348 Converter string 349 Formatter string 350 351 Location string 352 IndexVar string 353 KeyVar string 354 355 // instructs generator to skip the splitting and parsing from CollectionFormat 356 SkipParse bool 357 } 358 359 // ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array. 360 func (g *GenItems) ItemsDepth() string { 361 // NOTE: this is currently used by templates to generate explicit comments in nested structures 362 current := g 363 i := 1 364 for current.Parent != nil { 365 i++ 366 current = current.Parent 367 } 368 return strings.Repeat("items.", i) 369 } 370 371 // GenOperationGroup represents a named (tagged) group of operations 372 type GenOperationGroup struct { 373 GenCommon 374 Name string 375 Operations GenOperations 376 377 Summary string 378 Description string 379 Imports map[string]string 380 DefaultImports []string 381 RootPackage string 382 GenOpts *GenOpts 383 } 384 385 // GenOperationGroups is a sorted collection of operation groups 386 type GenOperationGroups []GenOperationGroup 387 388 func (g GenOperationGroups) Len() int { return len(g) } 389 func (g GenOperationGroups) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 390 func (g GenOperationGroups) Less(i, j int) bool { return g[i].Name < g[j].Name } 391 392 // GenStatusCodeResponses a container for status code responses 393 type GenStatusCodeResponses []GenResponse 394 395 func (g GenStatusCodeResponses) Len() int { return len(g) } 396 func (g GenStatusCodeResponses) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 397 func (g GenStatusCodeResponses) Less(i, j int) bool { return g[i].Code < g[j].Code } 398 399 // MarshalJSON marshals these responses to json 400 func (g GenStatusCodeResponses) MarshalJSON() ([]byte, error) { 401 if g == nil { 402 return nil, nil 403 } 404 var buf bytes.Buffer 405 buf.WriteRune('{') 406 for i, v := range g { 407 rb, err := json.Marshal(v) 408 if err != nil { 409 return nil, err 410 } 411 if i > 0 { 412 buf.WriteRune(',') 413 } 414 buf.WriteString(fmt.Sprintf("%q:", strconv.Itoa(v.Code))) 415 buf.Write(rb) 416 } 417 buf.WriteRune('}') 418 return buf.Bytes(), nil 419 } 420 421 // UnmarshalJSON unmarshals this GenStatusCodeResponses from json 422 func (g *GenStatusCodeResponses) UnmarshalJSON(data []byte) error { 423 var dd map[string]GenResponse 424 if err := json.Unmarshal(data, &dd); err != nil { 425 return err 426 } 427 var gg GenStatusCodeResponses 428 for _, v := range dd { 429 gg = append(gg, v) 430 } 431 sort.Sort(gg) 432 *g = gg 433 return nil 434 } 435 436 // GenOperation represents an operation for code generation 437 type GenOperation struct { 438 GenCommon 439 Package string 440 ReceiverName string 441 Name string 442 Summary string 443 Description string 444 Method string 445 Path string 446 BasePath string 447 Tags []string 448 RootPackage string 449 450 Imports map[string]string 451 DefaultImports []string 452 ExtraSchemas GenSchemaList 453 454 Authorized bool 455 Security []GenSecurityRequirements 456 SecurityDefinitions GenSecuritySchemes 457 Principal string 458 459 SuccessResponse *GenResponse 460 SuccessResponses []GenResponse 461 Responses GenStatusCodeResponses 462 DefaultResponse *GenResponse 463 464 Params GenParameters 465 QueryParams GenParameters 466 PathParams GenParameters 467 HeaderParams GenParameters 468 FormParams GenParameters 469 HasQueryParams bool 470 HasPathParams bool 471 HasHeaderParams bool 472 HasFormParams bool 473 HasFormValueParams bool 474 HasFileParams bool 475 HasBodyParams bool 476 HasStreamingResponse bool 477 478 Schemes []string 479 ExtraSchemes []string 480 ProducesMediaTypes []string 481 ConsumesMediaTypes []string 482 TimeoutName string 483 484 Extensions map[string]interface{} 485 } 486 487 // GenOperations represents a list of operations to generate 488 // this implements a sort by operation id 489 type GenOperations []GenOperation 490 491 func (g GenOperations) Len() int { return len(g) } 492 func (g GenOperations) Less(i, j int) bool { return g[i].Name < g[j].Name } 493 func (g GenOperations) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 494 495 // GenApp represents all the meta data needed to generate an application 496 // from a swagger spec 497 type GenApp struct { 498 GenCommon 499 APIPackage string 500 Package string 501 ReceiverName string 502 Name string 503 Principal string 504 DefaultConsumes string 505 DefaultProduces string 506 Host string 507 BasePath string 508 Info *spec.Info 509 ExternalDocs *spec.ExternalDocumentation 510 Imports map[string]string 511 DefaultImports []string 512 Schemes []string 513 ExtraSchemes []string 514 Consumes GenSerGroups 515 Produces GenSerGroups 516 SecurityDefinitions GenSecuritySchemes 517 Models []GenDefinition 518 Operations GenOperations 519 OperationGroups GenOperationGroups 520 SwaggerJSON string 521 // Embedded specs: this is important for when the generated server adds routes. 522 // NOTE: there is a distinct advantage to having this in runtime rather than generated code. 523 // We are noti ever going to generate the router. 524 // If embedding spec is an issue (e.g. memory usage), this can be excluded with the --exclude-spec 525 // generation option. Alternative methods to serve spec (e.g. from disk, ...) may be implemented by 526 // adding a middleware to the generated API. 527 FlatSwaggerJSON string 528 ExcludeSpec bool 529 GenOpts *GenOpts 530 } 531 532 // UseGoStructFlags returns true when no strategy is specified or it is set to "go-flags" 533 func (g *GenApp) UseGoStructFlags() bool { 534 if g.GenOpts == nil { 535 return true 536 } 537 return g.GenOpts.FlagStrategy == "" || g.GenOpts.FlagStrategy == "go-flags" 538 } 539 540 // UsePFlags returns true when the flag strategy is set to pflag 541 func (g *GenApp) UsePFlags() bool { 542 return g.GenOpts != nil && strings.HasPrefix(g.GenOpts.FlagStrategy, "pflag") 543 } 544 545 // UseIntermediateMode for https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29 546 func (g *GenApp) UseIntermediateMode() bool { 547 return g.GenOpts != nil && g.GenOpts.CompatibilityMode == "intermediate" 548 } 549 550 // UseModernMode for https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility 551 func (g *GenApp) UseModernMode() bool { 552 return g.GenOpts == nil || g.GenOpts.CompatibilityMode == "" || g.GenOpts.CompatibilityMode == "modern" 553 } 554 555 // GenSerGroups sorted representation of serializer groups 556 type GenSerGroups []GenSerGroup 557 558 func (g GenSerGroups) Len() int { return len(g) } 559 func (g GenSerGroups) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 560 func (g GenSerGroups) Less(i, j int) bool { return g[i].MediaType < g[j].MediaType } 561 562 // GenSerGroup represents a group of serializers, most likely this is a media type to a list of 563 // prioritized serializers. 564 type GenSerGroup struct { 565 ReceiverName string 566 AppName string 567 Name string 568 MediaType string 569 Implementation string 570 AllSerializers GenSerializers 571 } 572 573 // GenSerializers sorted representation of serializers 574 type GenSerializers []GenSerializer 575 576 func (g GenSerializers) Len() int { return len(g) } 577 func (g GenSerializers) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 578 func (g GenSerializers) Less(i, j int) bool { return g[i].MediaType < g[j].MediaType } 579 580 // GenSerializer represents a single serializer for a particular media type 581 type GenSerializer struct { 582 ReceiverName string 583 AppName string 584 Name string 585 MediaType string 586 Implementation string 587 } 588 589 // GenSecurityScheme represents a security scheme for code generation 590 type GenSecurityScheme struct { 591 AppName string 592 ID string 593 Name string 594 ReceiverName string 595 IsBasicAuth bool 596 IsAPIKeyAuth bool 597 IsOAuth2 bool 598 Scopes []string 599 Source string 600 Principal string 601 // from spec.SecurityScheme 602 Description string 603 Type string 604 In string 605 Flow string 606 AuthorizationURL string 607 TokenURL string 608 Extensions map[string]interface{} 609 } 610 611 // GenSecuritySchemes sorted representation of serializers 612 type GenSecuritySchemes []GenSecurityScheme 613 614 func (g GenSecuritySchemes) Len() int { return len(g) } 615 func (g GenSecuritySchemes) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 616 func (g GenSecuritySchemes) Less(i, j int) bool { return g[i].ID < g[j].ID } 617 618 // GenSecurityRequirement represents a security requirement for an operation 619 type GenSecurityRequirement struct { 620 Name string 621 Scopes []string 622 } 623 624 // GenSecurityRequirements represents a compounded security requirement specification. 625 // In a []GenSecurityRequirements complete requirements specification, 626 // outer elements are interpreted as optional requirements (OR), and 627 // inner elements are interpreted as jointly required (AND). 628 type GenSecurityRequirements []GenSecurityRequirement 629 630 func (g GenSecurityRequirements) Len() int { return len(g) } 631 func (g GenSecurityRequirements) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 632 func (g GenSecurityRequirements) Less(i, j int) bool { return g[i].Name < g[j].Name }