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