1package generator
2
3import (
4	"bytes"
5	"encoding/json"
6	"fmt"
7	"sort"
8	"strconv"
9	"strings"
10
11	"github.com/go-openapi/analysis"
12	"github.com/go-openapi/spec"
13)
14
15// GenCommon contains common properties needed across
16// definitions, app and operations
17// TargetImportPath may be used by templates to import other (possibly
18// generated) packages in the generation path (e.g. relative to GOPATH).
19// TargetImportPath is NOT used by standard templates.
20type GenCommon struct {
21	Copyright        string
22	TargetImportPath string
23}
24
25// GenDefinition contains all the properties to generate a
26// definition from a swagger spec
27type GenDefinition struct {
28	GenCommon
29	GenSchema
30	Package        string
31	Imports        map[string]string
32	DefaultImports map[string]string
33	ExtraSchemas   GenSchemaList
34	DependsOn      []string
35	External       bool
36}
37
38// GenDefinitions represents a list of operations to generate
39// this implements a sort by operation id
40type GenDefinitions []GenDefinition
41
42func (g GenDefinitions) Len() int           { return len(g) }
43func (g GenDefinitions) Less(i, j int) bool { return g[i].Name < g[j].Name }
44func (g GenDefinitions) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
45
46// GenSchemaList is a list of schemas for generation.
47//
48// It can be sorted by name to get a stable struct layout for
49// version control and such
50type GenSchemaList []GenSchema
51
52// GenSchema contains all the information needed to generate the code
53// for a schema
54type GenSchema struct {
55	resolvedType
56	sharedValidations
57	Example                    string
58	OriginalName               string
59	Name                       string
60	Suffix                     string
61	Path                       string
62	ValueExpression            string
63	IndexVar                   string
64	KeyVar                     string
65	Title                      string
66	Description                string
67	Location                   string
68	ReceiverName               string
69	Items                      *GenSchema
70	AllowsAdditionalItems      bool
71	HasAdditionalItems         bool
72	AdditionalItems            *GenSchema
73	Object                     *GenSchema
74	XMLName                    string
75	CustomTag                  string
76	Properties                 GenSchemaList
77	AllOf                      GenSchemaList
78	HasAdditionalProperties    bool
79	IsAdditionalProperties     bool
80	AdditionalProperties       *GenSchema
81	StrictAdditionalProperties bool
82	ReadOnly                   bool
83	IsVirtual                  bool
84	IsBaseType                 bool
85	HasBaseType                bool
86	IsSubType                  bool
87	IsExported                 bool
88	DiscriminatorField         string
89	DiscriminatorValue         string
90	Discriminates              map[string]string
91	Parents                    []string
92	IncludeValidator           bool
93	IncludeModel               bool
94	Default                    interface{}
95	WantsMarshalBinary         bool // do we generate MarshalBinary interface?
96	StructTags                 []string
97	ExtraImports               map[string]string // non-standard imports detected when using external types
98	ExternalDocs               *spec.ExternalDocumentation
99}
100
101func (g GenSchema) renderMarshalTag() string {
102	if g.HasBaseType {
103		return "-"
104	}
105
106	var result strings.Builder
107
108	result.WriteString(g.OriginalName)
109
110	if !g.Required && g.IsEmptyOmitted {
111		result.WriteString(",omitempty")
112	}
113
114	if g.IsJSONString {
115		result.WriteString(",string")
116	}
117
118	return result.String()
119}
120
121// PrintTags takes care of rendering tags for a struct field
122func (g GenSchema) PrintTags() string {
123	tags := make(map[string]string, 3)
124	orderedTags := make([]string, 0, 3)
125
126	tags["json"] = g.renderMarshalTag()
127	orderedTags = append(orderedTags, "json")
128
129	if len(g.XMLName) > 0 {
130		if !g.Required && g.IsEmptyOmitted {
131			tags["xml"] = g.XMLName + ",omitempty"
132		} else {
133			tags["xml"] = g.XMLName
134		}
135		orderedTags = append(orderedTags, "xml")
136	}
137
138	// Add extra struct tags, only if the tag hasn't already been set, i.e. example.
139	// Extra struct tags have the same value has the `json` tag.
140	for _, tag := range g.StructTags {
141		if _, exists := tags[tag]; exists {
142			// dedupe
143			continue
144		}
145
146		if tag == "example" && len(g.Example) > 0 {
147			// only add example tag if it's contained in the struct tags
148			tags["example"] = g.Example // json representation of the example object
149		} else if tag == "description" && len(g.Description) > 0 {
150			tags["description"] = g.Description
151		} else {
152			tags[tag] = tags["json"]
153		}
154
155		orderedTags = append(orderedTags, tag)
156	}
157
158	// Assemble the tags in key value pairs with the value properly quoted.
159	kvPairs := make([]string, 0, len(orderedTags)+1)
160	for _, key := range orderedTags {
161		kvPairs = append(kvPairs, fmt.Sprintf("%s:%s", key, strconv.Quote(tags[key])))
162	}
163
164	if len(g.CustomTag) > 0 {
165		kvPairs = append(kvPairs, g.CustomTag)
166	}
167
168	// Join the key value pairs by a space.
169	completeTag := strings.Join(kvPairs, " ")
170
171	// If the values contain a backtick, we cannot render the tag using backticks because Go does not support
172	// escaping backticks in raw string literals.
173	valuesHaveBacktick := false
174	for _, value := range tags {
175		if !strconv.CanBackquote(value) {
176			valuesHaveBacktick = true
177			break
178		}
179	}
180
181	if !valuesHaveBacktick {
182		return fmt.Sprintf("`%s`", completeTag)
183	}
184
185	// We have to escape the tag again to put it in a literal with double quotes as the tag format uses double quotes.
186	return strconv.Quote(completeTag)
187}
188
189// UnderlyingType tells the go type or the aliased go type
190func (g GenSchema) UnderlyingType() string {
191	if g.IsAliased {
192		return g.AliasedType
193	}
194	return g.GoType
195}
196
197// ToString returns a string conversion expression for the schema
198func (g GenSchema) ToString() string {
199	return g.resolvedType.ToString(g.ValueExpression)
200}
201
202func (g GenSchemaList) Len() int      { return len(g) }
203func (g GenSchemaList) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
204func (g GenSchemaList) Less(i, j int) bool {
205	a, okA := g[i].Extensions[xOrder].(float64)
206	b, okB := g[j].Extensions[xOrder].(float64)
207
208	// If both properties have x-order defined, then the one with lower x-order is smaller
209	if okA && okB {
210		return a < b
211	}
212
213	// If only the first property has x-order defined, then it is smaller
214	if okA {
215		return true
216	}
217
218	// If only the second property has x-order defined, then it is smaller
219	if okB {
220		return false
221	}
222
223	// If neither property has x-order defined, then the one with lower lexicographic name is smaller
224	return g[i].Name < g[j].Name
225}
226
227type sharedValidations struct {
228	spec.SchemaValidations
229
230	HasValidations        bool
231	HasContextValidations bool
232	Required              bool
233	HasSliceValidations   bool
234	ItemsEnum             []interface{}
235
236	// NOTE: "patternProperties" and "dependencies" not supported by Swagger 2.0
237}
238
239// GenResponse represents a response object for code generation
240type GenResponse struct {
241	Package       string
242	ModelsPackage string
243	ReceiverName  string
244	Name          string
245	Description   string
246
247	IsSuccess bool
248
249	Code               int
250	Method             string
251	Path               string
252	Headers            GenHeaders
253	Schema             *GenSchema
254	AllowsForStreaming bool
255
256	Imports        map[string]string
257	DefaultImports map[string]string
258
259	Extensions map[string]interface{}
260
261	StrictResponders bool
262	OperationName    string
263	Examples         GenResponseExamples
264}
265
266// GenResponseExamples is a sortable collection []GenResponseExample
267type GenResponseExamples []GenResponseExample
268
269func (g GenResponseExamples) Len() int           { return len(g) }
270func (g GenResponseExamples) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
271func (g GenResponseExamples) Less(i, j int) bool { return g[i].MediaType < g[j].MediaType }
272
273// GenResponseExample captures an example provided for a response for some mime type
274type GenResponseExample struct {
275	MediaType string
276	Example   interface{}
277}
278
279// GenHeader represents a header on a response for code generation
280type GenHeader struct {
281	resolvedType
282	sharedValidations
283
284	Package      string
285	ReceiverName string
286	IndexVar     string
287
288	ID              string
289	Name            string
290	Path            string
291	ValueExpression string
292
293	Title       string
294	Description string
295	Default     interface{}
296	HasDefault  bool
297
298	CollectionFormat string
299
300	Child  *GenItems
301	Parent *GenItems
302
303	Converter string
304	Formatter string
305
306	ZeroValue string
307}
308
309// ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array.
310// For a header objects it always returns "".
311func (h *GenHeader) ItemsDepth() string {
312	// NOTE: this is currently used by templates to generate explicit comments in nested structures
313	return ""
314}
315
316// ToString returns a string conversion expression for the header
317func (h GenHeader) ToString() string {
318	return h.resolvedType.ToString(h.ValueExpression)
319}
320
321// GenHeaders is a sorted collection of headers for codegen
322type GenHeaders []GenHeader
323
324func (g GenHeaders) Len() int           { return len(g) }
325func (g GenHeaders) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
326func (g GenHeaders) Less(i, j int) bool { return g[i].Name < g[j].Name }
327
328// HasSomeDefaults returns true is at least one header has a default value set
329func (g GenHeaders) HasSomeDefaults() bool {
330	// NOTE: this is currently used by templates to avoid empty constructs
331	for _, header := range g {
332		if header.HasDefault {
333			return true
334		}
335	}
336	return false
337}
338
339// GenParameter is used to represent
340// a parameter or a header for code generation.
341type GenParameter struct {
342	resolvedType
343	sharedValidations
344
345	ID              string
346	Name            string
347	ModelsPackage   string
348	Path            string
349	ValueExpression string
350	IndexVar        string
351	KeyVar          string
352	ReceiverName    string
353	Location        string
354	Title           string
355	Description     string
356	Converter       string
357	Formatter       string
358
359	Schema *GenSchema
360
361	CollectionFormat string
362
363	Child  *GenItems
364	Parent *GenItems
365
366	// Unused
367	// BodyParam *GenParameter
368
369	Default         interface{}
370	HasDefault      bool
371	ZeroValue       string
372	AllowEmptyValue bool
373
374	// validation strategy for Body params, which may mix model and simple constructs.
375	// Distinguish the following cases:
376	// - HasSimpleBodyParams: body is an inline simple type
377	// - HasModelBodyParams: body is a model objectd
378	// - HasSimpleBodyItems: body is an inline array of simple type
379	// - HasModelBodyItems: body is an array of model objects
380	// - HasSimpleBodyMap: body is a map of simple objects (possibly arrays)
381	// - HasModelBodyMap: body is a map of model objects
382	HasSimpleBodyParams bool
383	HasModelBodyParams  bool
384	HasSimpleBodyItems  bool
385	HasModelBodyItems   bool
386	HasSimpleBodyMap    bool
387	HasModelBodyMap     bool
388
389	Extensions map[string]interface{}
390}
391
392// IsQueryParam returns true when this parameter is a query param
393func (g *GenParameter) IsQueryParam() bool {
394	return g.Location == "query"
395}
396
397// IsPathParam returns true when this parameter is a path param
398func (g *GenParameter) IsPathParam() bool {
399	return g.Location == "path"
400}
401
402// IsFormParam returns true when this parameter is a form param
403func (g *GenParameter) IsFormParam() bool {
404	return g.Location == "formData"
405}
406
407// IsHeaderParam returns true when this parameter is a header param
408func (g *GenParameter) IsHeaderParam() bool {
409	return g.Location == "header"
410}
411
412// IsBodyParam returns true when this parameter is a body param
413func (g *GenParameter) IsBodyParam() bool {
414	return g.Location == "body"
415}
416
417// IsFileParam returns true when this parameter is a file param
418func (g *GenParameter) IsFileParam() bool {
419	return g.SwaggerType == "file"
420}
421
422// ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array.
423// For a parameter object, it always returns "".
424func (g *GenParameter) ItemsDepth() string {
425	// NOTE: this is currently used by templates to generate explicit comments in nested structures
426	return ""
427}
428
429// UnderlyingType tells the go type or the aliased go type
430func (g GenParameter) UnderlyingType() string {
431	return g.GoType
432}
433
434// ToString returns a string conversion expression for the parameter
435func (g GenParameter) ToString() string {
436	return g.resolvedType.ToString(g.ValueExpression)
437}
438
439// GenParameters represents a sorted parameter collection
440type GenParameters []GenParameter
441
442func (g GenParameters) Len() int           { return len(g) }
443func (g GenParameters) Less(i, j int) bool { return g[i].Name < g[j].Name }
444func (g GenParameters) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
445
446// HasSomeDefaults returns true is at least one parameter has a default value set
447func (g GenParameters) HasSomeDefaults() bool {
448	// NOTE: this is currently used by templates to avoid empty constructs
449	for _, param := range g {
450		if param.HasDefault {
451			return true
452		}
453	}
454	return false
455}
456
457// GenItems represents the collection items for a collection parameter
458type GenItems struct {
459	sharedValidations
460	resolvedType
461
462	Name             string
463	Path             string
464	ValueExpression  string
465	CollectionFormat string
466	Child            *GenItems
467	Parent           *GenItems
468	Converter        string
469	Formatter        string
470
471	Location string
472	IndexVar string
473	KeyVar   string
474
475	// instructs generator to skip the splitting and parsing from CollectionFormat
476	SkipParse bool
477	// instructs generator that some nested structure needs an higher level loop index
478	NeedsIndex bool
479}
480
481// ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array.
482func (g *GenItems) ItemsDepth() string {
483	// NOTE: this is currently used by templates to generate explicit comments in nested structures
484	current := g
485	i := 1
486	for current.Parent != nil {
487		i++
488		current = current.Parent
489	}
490	return strings.Repeat("items.", i)
491}
492
493// UnderlyingType tells the go type or the aliased go type
494func (g GenItems) UnderlyingType() string {
495	return g.GoType
496}
497
498// ToString returns a string conversion expression for the item
499func (g GenItems) ToString() string {
500	return g.resolvedType.ToString(g.ValueExpression)
501}
502
503// GenOperationGroup represents a named (tagged) group of operations
504type GenOperationGroup struct {
505	GenCommon
506	Name       string
507	Operations GenOperations
508
509	Summary        string
510	Description    string
511	Imports        map[string]string
512	DefaultImports map[string]string
513	RootPackage    string
514	GenOpts        *GenOpts
515	PackageAlias   string
516}
517
518// GenOperationGroups is a sorted collection of operation groups
519type GenOperationGroups []GenOperationGroup
520
521func (g GenOperationGroups) Len() int           { return len(g) }
522func (g GenOperationGroups) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
523func (g GenOperationGroups) Less(i, j int) bool { return g[i].Name < g[j].Name }
524
525// GenStatusCodeResponses a container for status code responses
526type GenStatusCodeResponses []GenResponse
527
528func (g GenStatusCodeResponses) Len() int           { return len(g) }
529func (g GenStatusCodeResponses) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
530func (g GenStatusCodeResponses) Less(i, j int) bool { return g[i].Code < g[j].Code }
531
532// MarshalJSON marshals these responses to json
533//
534// This is used by DumpData.
535func (g GenStatusCodeResponses) MarshalJSON() ([]byte, error) {
536	if g == nil {
537		return nil, nil
538	}
539	responses := make(GenStatusCodeResponses, len(g))
540	copy(responses, g)
541	// order marshalled output
542	sort.Sort(responses)
543
544	var buf bytes.Buffer
545	buf.WriteRune('{')
546	for i, v := range responses {
547		rb, err := json.Marshal(v)
548		if err != nil {
549			return nil, err
550		}
551		if i > 0 {
552			buf.WriteRune(',')
553		}
554		buf.WriteString(fmt.Sprintf("%q:", strconv.Itoa(v.Code)))
555		buf.Write(rb)
556	}
557	buf.WriteRune('}')
558	return buf.Bytes(), nil
559}
560
561// UnmarshalJSON unmarshals this GenStatusCodeResponses from json
562func (g *GenStatusCodeResponses) UnmarshalJSON(data []byte) error {
563	var dd map[string]GenResponse
564	if err := json.Unmarshal(data, &dd); err != nil {
565		return err
566	}
567	var gg GenStatusCodeResponses
568	for _, v := range dd {
569		gg = append(gg, v)
570	}
571	sort.Sort(gg)
572	*g = gg
573	return nil
574}
575
576// GenOperation represents an operation for code generation
577type GenOperation struct {
578	GenCommon
579	Package      string
580	ReceiverName string
581	Name         string
582	Summary      string
583	Description  string
584	Method       string
585	Path         string
586	BasePath     string
587	Tags         []string
588	UseTags      bool
589	RootPackage  string
590
591	Imports        map[string]string
592	DefaultImports map[string]string
593	ExtraSchemas   GenSchemaList
594	PackageAlias   string
595
596	Authorized           bool
597	Security             []GenSecurityRequirements // resolved security requirements for the operation
598	SecurityDefinitions  GenSecuritySchemes
599	SecurityRequirements []analysis.SecurityRequirement // original security requirements as per the spec (for doc)
600	Principal            string
601	PrincipalIsNullable  bool
602
603	SuccessResponse  *GenResponse
604	SuccessResponses []GenResponse
605	Responses        GenStatusCodeResponses
606	DefaultResponse  *GenResponse
607
608	Params               GenParameters
609	QueryParams          GenParameters
610	PathParams           GenParameters
611	HeaderParams         GenParameters
612	FormParams           GenParameters
613	HasQueryParams       bool
614	HasPathParams        bool
615	HasHeaderParams      bool
616	HasFormParams        bool
617	HasFormValueParams   bool
618	HasFileParams        bool
619	HasBodyParams        bool
620	HasStreamingResponse bool
621
622	Schemes              []string
623	ExtraSchemes         []string
624	SchemeOverrides      []string // original scheme overrides for operation, as per spec (for doc)
625	ExtraSchemeOverrides []string // original extra scheme overrides for operation, as per spec (for doc)
626	ProducesMediaTypes   []string
627	ConsumesMediaTypes   []string
628	TimeoutName          string
629
630	Extensions map[string]interface{}
631
632	StrictResponders bool
633	ExternalDocs     *spec.ExternalDocumentation
634	Produces         []string // original produces for operation (for doc)
635	Consumes         []string // original consumes for operation (for doc)
636}
637
638// GenOperations represents a list of operations to generate
639// this implements a sort by operation id
640type GenOperations []GenOperation
641
642func (g GenOperations) Len() int           { return len(g) }
643func (g GenOperations) Less(i, j int) bool { return g[i].Name < g[j].Name }
644func (g GenOperations) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
645
646// GenApp represents all the meta data needed to generate an application
647// from a swagger spec
648type GenApp struct {
649	GenCommon
650	APIPackage                 string
651	ServerPackageAlias         string
652	ImplementationPackageAlias string
653	APIPackageAlias            string
654	Package                    string
655	ReceiverName               string
656	Name                       string
657	Principal                  string
658	PrincipalIsNullable        bool
659	DefaultConsumes            string
660	DefaultProduces            string
661	Host                       string
662	BasePath                   string
663	Info                       *spec.Info
664	ExternalDocs               *spec.ExternalDocumentation
665	Tags                       []spec.Tag
666	Imports                    map[string]string
667	DefaultImports             map[string]string
668	Schemes                    []string
669	ExtraSchemes               []string
670	Consumes                   GenSerGroups
671	Produces                   GenSerGroups
672	SecurityDefinitions        GenSecuritySchemes
673	SecurityRequirements       []analysis.SecurityRequirement // original security requirements as per the spec (for doc)
674	Models                     []GenDefinition
675	Operations                 GenOperations
676	OperationGroups            GenOperationGroups
677	SwaggerJSON                string
678	// Embedded specs: this is important for when the generated server adds routes.
679	// NOTE: there is a distinct advantage to having this in runtime rather than generated code.
680	// We are not ever going to generate the router.
681	// If embedding spec is an issue (e.g. memory usage), this can be excluded with the --exclude-spec
682	// generation option. Alternative methods to serve spec (e.g. from disk, ...) may be implemented by
683	// adding a middleware to the generated API.
684	FlatSwaggerJSON string
685	ExcludeSpec     bool
686	GenOpts         *GenOpts
687}
688
689// UseGoStructFlags returns true when no strategy is specified or it is set to "go-flags"
690func (g *GenApp) UseGoStructFlags() bool {
691	if g.GenOpts == nil {
692		return true
693	}
694	return g.GenOpts.FlagStrategy == "" || g.GenOpts.FlagStrategy == "go-flags"
695}
696
697// UsePFlags returns true when the flag strategy is set to pflag
698func (g *GenApp) UsePFlags() bool {
699	return g.GenOpts != nil && strings.HasPrefix(g.GenOpts.FlagStrategy, "pflag")
700}
701
702// UseFlags returns true when the flag strategy is set to flag
703func (g *GenApp) UseFlags() bool {
704	return g.GenOpts != nil && strings.HasPrefix(g.GenOpts.FlagStrategy, "flag")
705}
706
707// UseIntermediateMode for https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29
708func (g *GenApp) UseIntermediateMode() bool {
709	return g.GenOpts != nil && g.GenOpts.CompatibilityMode == "intermediate"
710}
711
712// UseModernMode for https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
713func (g *GenApp) UseModernMode() bool {
714	return g.GenOpts == nil || g.GenOpts.CompatibilityMode == "" || g.GenOpts.CompatibilityMode == "modern"
715}
716
717// GenSerGroups sorted representation of serializer groups
718type GenSerGroups []GenSerGroup
719
720func (g GenSerGroups) Len() int           { return len(g) }
721func (g GenSerGroups) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
722func (g GenSerGroups) Less(i, j int) bool { return g[i].Name < g[j].Name }
723
724// GenSerGroup represents a group of serializers: this links a serializer to a list of
725// prioritized media types (mime).
726type GenSerGroup struct {
727	GenSerializer
728
729	// All media types for this serializer. The redundant representation allows for easier use in templates
730	AllSerializers GenSerializers
731}
732
733// GenSerializers sorted representation of serializers
734type GenSerializers []GenSerializer
735
736func (g GenSerializers) Len() int           { return len(g) }
737func (g GenSerializers) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
738func (g GenSerializers) Less(i, j int) bool { return g[i].MediaType < g[j].MediaType }
739
740// GenSerializer represents a single serializer for a particular media type
741type GenSerializer struct {
742	AppName        string // Application name
743	ReceiverName   string
744	Name           string   // Name of the Producer/Consumer (e.g. json, yaml, txt, bin)
745	MediaType      string   // mime
746	Implementation string   // func implementing the Producer/Consumer
747	Parameters     []string // parameters supported by this serializer
748}
749
750// GenSecurityScheme represents a security scheme for code generation
751type GenSecurityScheme struct {
752	AppName             string
753	ID                  string
754	Name                string
755	ReceiverName        string
756	IsBasicAuth         bool
757	IsAPIKeyAuth        bool
758	IsOAuth2            bool
759	Scopes              []string
760	Source              string
761	Principal           string
762	PrincipalIsNullable bool
763
764	// from spec.SecurityScheme
765	Description      string
766	Type             string
767	In               string
768	Flow             string
769	AuthorizationURL string
770	TokenURL         string
771	Extensions       map[string]interface{}
772	ScopesDesc       []GenSecurityScope
773}
774
775// GenSecuritySchemes sorted representation of serializers
776type GenSecuritySchemes []GenSecurityScheme
777
778func (g GenSecuritySchemes) Len() int           { return len(g) }
779func (g GenSecuritySchemes) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
780func (g GenSecuritySchemes) Less(i, j int) bool { return g[i].ID < g[j].ID }
781
782// GenSecurityRequirement represents a security requirement for an operation
783type GenSecurityRequirement struct {
784	Name   string
785	Scopes []string
786}
787
788// GenSecurityScope represents a scope descriptor for an OAuth2 security scheme
789type GenSecurityScope struct {
790	Name        string
791	Description string
792}
793
794// GenSecurityRequirements represents a compounded security requirement specification.
795// In a []GenSecurityRequirements complete requirements specification,
796// outer elements are interpreted as optional requirements (OR), and
797// inner elements are interpreted as jointly required (AND).
798type GenSecurityRequirements []GenSecurityRequirement
799
800func (g GenSecurityRequirements) Len() int           { return len(g) }
801func (g GenSecurityRequirements) Swap(i, j int)      { g[i], g[j] = g[j], g[i] }
802func (g GenSecurityRequirements) Less(i, j int) bool { return g[i].Name < g[j].Name }
803