github.com/hsdp/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 }