github.com/ManabuSeki/goa-v1@v1.4.3/goagen/gen_app/writers_test.go (about)

     1  package genapp_test
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  
     7  	"github.com/goadesign/goa/design"
     8  	"github.com/goadesign/goa/design/apidsl"
     9  	"github.com/goadesign/goa/dslengine"
    10  	"github.com/goadesign/goa/goagen/codegen"
    11  	genapp "github.com/goadesign/goa/goagen/gen_app"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("ContextsWriter", func() {
    17  	var writer *genapp.ContextsWriter
    18  	var filename string
    19  	var workspace *codegen.Workspace
    20  
    21  	JustBeforeEach(func() {
    22  		var err error
    23  		workspace, err = codegen.NewWorkspace("test")
    24  		Ω(err).ShouldNot(HaveOccurred())
    25  		pkg, err := workspace.NewPackage("contexts")
    26  		Ω(err).ShouldNot(HaveOccurred())
    27  		src, err := pkg.CreateSourceFile("test.go")
    28  		Ω(err).ShouldNot(HaveOccurred())
    29  		defer src.Close()
    30  		filename = src.Abs()
    31  		writer, err = genapp.NewContextsWriter(filename)
    32  		Ω(err).ShouldNot(HaveOccurred())
    33  		codegen.TempCount = 0
    34  	})
    35  
    36  	AfterEach(func() {
    37  		workspace.Delete()
    38  	})
    39  
    40  	Context("correctly configured", func() {
    41  		var f *os.File
    42  		BeforeEach(func() {
    43  			dslengine.Reset()
    44  			f, _ = ioutil.TempFile("", "")
    45  			filename = f.Name()
    46  		})
    47  
    48  		AfterEach(func() {
    49  			os.Remove(filename)
    50  		})
    51  
    52  		Context("with data", func() {
    53  			var params, headers *design.AttributeDefinition
    54  			var payload *design.UserTypeDefinition
    55  			var responses map[string]*design.ResponseDefinition
    56  			var routes []*design.RouteDefinition
    57  
    58  			var data *genapp.ContextTemplateData
    59  
    60  			BeforeEach(func() {
    61  				params = nil
    62  				headers = nil
    63  				payload = nil
    64  				responses = nil
    65  				routes = nil
    66  				data = nil
    67  			})
    68  
    69  			JustBeforeEach(func() {
    70  				data = &genapp.ContextTemplateData{
    71  					Name:         "ListBottleContext",
    72  					ResourceName: "bottles",
    73  					ActionName:   "list",
    74  					Params:       params,
    75  					Payload:      payload,
    76  					Headers:      headers,
    77  					Responses:    responses,
    78  					Routes:       routes,
    79  					API:          design.Design,
    80  					DefaultPkg:   "",
    81  				}
    82  			})
    83  
    84  			Context("with simple data", func() {
    85  				It("writes the simple contexts code", func() {
    86  					err := writer.Execute(data)
    87  					Ω(err).ShouldNot(HaveOccurred())
    88  					b, err := ioutil.ReadFile(filename)
    89  					Ω(err).ShouldNot(HaveOccurred())
    90  					written := string(b)
    91  					Ω(written).ShouldNot(BeEmpty())
    92  					Ω(written).Should(ContainSubstring(emptyContext))
    93  					Ω(written).Should(ContainSubstring(emptyContextFactory))
    94  				})
    95  			})
    96  
    97  			Context("with a media type setting a ContentType", func() {
    98  				var contentType = "application/json"
    99  
   100  				BeforeEach(func() {
   101  					mediaType := &design.MediaTypeDefinition{
   102  						UserTypeDefinition: &design.UserTypeDefinition{
   103  							AttributeDefinition: &design.AttributeDefinition{
   104  								Type: design.Object{"foo": {Type: design.String}},
   105  							},
   106  						},
   107  						Identifier:  "application/vnd.goa.test",
   108  						ContentType: contentType,
   109  					}
   110  					defView := &design.ViewDefinition{
   111  						AttributeDefinition: mediaType.AttributeDefinition,
   112  						Name:                "default",
   113  						Parent:              mediaType,
   114  					}
   115  					mediaType.Views = map[string]*design.ViewDefinition{"default": defView}
   116  					design.Design = new(design.APIDefinition)
   117  					design.Design.MediaTypes = map[string]*design.MediaTypeDefinition{
   118  						design.CanonicalIdentifier(mediaType.Identifier): mediaType,
   119  					}
   120  					design.ProjectedMediaTypes = make(map[string]*design.MediaTypeDefinition)
   121  					responses = map[string]*design.ResponseDefinition{"OK": {
   122  						Name:      "OK",
   123  						Status:    200,
   124  						MediaType: mediaType.Identifier,
   125  					}}
   126  				})
   127  
   128  				It("the generated code sets the Content-Type header", func() {
   129  					err := writer.Execute(data)
   130  					Ω(err).ShouldNot(HaveOccurred())
   131  					b, err := ioutil.ReadFile(filename)
   132  					Ω(err).ShouldNot(HaveOccurred())
   133  					written := string(b)
   134  					Ω(written).ShouldNot(BeEmpty())
   135  					Ω(written).Should(ContainSubstring(`ctx.ResponseData.Header().Set("Content-Type", "` + contentType + `")`))
   136  				})
   137  			})
   138  
   139  			Context("with a collection media type", func() {
   140  				BeforeEach(func() {
   141  					elemType := &design.MediaTypeDefinition{
   142  						UserTypeDefinition: &design.UserTypeDefinition{
   143  							AttributeDefinition: &design.AttributeDefinition{
   144  								Type: design.Object{"foo": {Type: design.String}},
   145  							},
   146  						},
   147  						Identifier: "application/vnd.goa.test",
   148  					}
   149  					defView := &design.ViewDefinition{
   150  						AttributeDefinition: elemType.AttributeDefinition,
   151  						Name:                "default",
   152  						Parent:              elemType,
   153  					}
   154  					elemType.Views = map[string]*design.ViewDefinition{"default": defView}
   155  					design.Design = new(design.APIDefinition)
   156  					design.Design.MediaTypes = map[string]*design.MediaTypeDefinition{
   157  						design.CanonicalIdentifier(elemType.Identifier): elemType,
   158  					}
   159  					design.ProjectedMediaTypes = make(map[string]*design.MediaTypeDefinition)
   160  					mediaType := apidsl.CollectionOf(elemType)
   161  					dslengine.Execute(mediaType.DSL(), mediaType)
   162  					responses = map[string]*design.ResponseDefinition{"OK": {
   163  						Name:   "OK",
   164  						Status: 200,
   165  						Type:   mediaType,
   166  					}}
   167  				})
   168  
   169  				It("the generated code sets the response to an empty collection if value is nil", func() {
   170  					err := writer.Execute(data)
   171  					Ω(err).ShouldNot(HaveOccurred())
   172  					b, err := ioutil.ReadFile(filename)
   173  					Ω(err).ShouldNot(HaveOccurred())
   174  					written := string(b)
   175  					Ω(written).ShouldNot(BeEmpty())
   176  					Ω(written).Should(ContainSubstring(`	if r == nil {
   177  		r = Collection{}
   178  	}
   179  	return ctx.ResponseData.Service.Send(ctx.Context, 200, r)`))
   180  				})
   181  			})
   182  
   183  			Context("with an integer param", func() {
   184  				var (
   185  					intParam   *design.AttributeDefinition
   186  					dataType   design.Object
   187  					validation *dslengine.ValidationDefinition
   188  				)
   189  
   190  				BeforeEach(func() {
   191  					intParam = &design.AttributeDefinition{Type: design.Integer}
   192  					dataType = design.Object{
   193  						"param": intParam,
   194  					}
   195  					validation = &dslengine.ValidationDefinition{}
   196  					params = &design.AttributeDefinition{
   197  						Type:       dataType,
   198  						Validation: validation,
   199  					}
   200  				})
   201  
   202  				It("writes the integer contexts code", func() {
   203  					err := writer.Execute(data)
   204  					Ω(err).ShouldNot(HaveOccurred())
   205  					b, err := ioutil.ReadFile(filename)
   206  					Ω(err).ShouldNot(HaveOccurred())
   207  					written := string(b)
   208  					Ω(written).ShouldNot(BeEmpty())
   209  					Ω(written).Should(ContainSubstring(intContext))
   210  					Ω(written).Should(ContainSubstring(intContextFactory))
   211  				})
   212  
   213  				Context("with a default value", func() {
   214  					BeforeEach(func() {
   215  						intParam.SetDefault(2)
   216  					})
   217  
   218  					It("writes the integer contexts code", func() {
   219  						err := writer.Execute(data)
   220  						Ω(err).ShouldNot(HaveOccurred())
   221  						b, err := ioutil.ReadFile(filename)
   222  						Ω(err).ShouldNot(HaveOccurred())
   223  						written := string(b)
   224  						Ω(written).ShouldNot(BeEmpty())
   225  						Ω(written).Should(ContainSubstring(intDefaultContext))
   226  						Ω(written).Should(ContainSubstring(intDefaultContextFactory))
   227  					})
   228  				})
   229  
   230  				Context("with required attribute", func() {
   231  					BeforeEach(func() {
   232  						validation.Required = []string{"param"}
   233  					})
   234  
   235  					It("writes the integer contexts code", func() {
   236  						err := writer.Execute(data)
   237  						Ω(err).ShouldNot(HaveOccurred())
   238  						b, err := ioutil.ReadFile(filename)
   239  						Ω(err).ShouldNot(HaveOccurred())
   240  						written := string(b)
   241  						Ω(written).ShouldNot(BeEmpty())
   242  						Ω(written).Should(ContainSubstring(intRequiredContext))
   243  						Ω(written).Should(ContainSubstring(intRequiredContextFactory))
   244  					})
   245  
   246  					Context("with a default value", func() {
   247  						BeforeEach(func() {
   248  							intParam.SetDefault(2)
   249  						})
   250  
   251  						It("writes the integer contexts code", func() {
   252  							err := writer.Execute(data)
   253  							Ω(err).ShouldNot(HaveOccurred())
   254  							b, err := ioutil.ReadFile(filename)
   255  							Ω(err).ShouldNot(HaveOccurred())
   256  							written := string(b)
   257  							Ω(written).ShouldNot(BeEmpty())
   258  							Ω(written).Should(ContainSubstring(intRequiredDefaultContext))
   259  							Ω(written).Should(ContainSubstring(intRequiredDefaultContextFactory))
   260  						})
   261  					})
   262  				})
   263  			})
   264  
   265  			Context("with an string param", func() {
   266  				var (
   267  					strParam   *design.AttributeDefinition
   268  					dataType   design.Object
   269  					validation *dslengine.ValidationDefinition
   270  				)
   271  
   272  				BeforeEach(func() {
   273  					strParam = &design.AttributeDefinition{Type: design.String}
   274  					dataType = design.Object{
   275  						"param": strParam,
   276  					}
   277  					validation = &dslengine.ValidationDefinition{}
   278  					params = &design.AttributeDefinition{
   279  						Type:       dataType,
   280  						Validation: validation,
   281  					}
   282  				})
   283  
   284  				It("writes the string contexts code", func() {
   285  					err := writer.Execute(data)
   286  					Ω(err).ShouldNot(HaveOccurred())
   287  					b, err := ioutil.ReadFile(filename)
   288  					Ω(err).ShouldNot(HaveOccurred())
   289  					written := string(b)
   290  					Ω(written).ShouldNot(BeEmpty())
   291  					Ω(written).Should(ContainSubstring(strContext))
   292  					Ω(written).Should(ContainSubstring(strContextFactory))
   293  				})
   294  
   295  				Context("with a default value", func() {
   296  					BeforeEach(func() {
   297  						strParam.SetDefault("foo")
   298  					})
   299  
   300  					It("writes the string contexts code", func() {
   301  						err := writer.Execute(data)
   302  						Ω(err).ShouldNot(HaveOccurred())
   303  						b, err := ioutil.ReadFile(filename)
   304  						Ω(err).ShouldNot(HaveOccurred())
   305  						written := string(b)
   306  						Ω(written).ShouldNot(BeEmpty())
   307  						Ω(written).Should(ContainSubstring(strNonOptionalContext))
   308  						Ω(written).Should(ContainSubstring(strDefaultContextFactory))
   309  					})
   310  				})
   311  
   312  				Context("with required attribute", func() {
   313  					BeforeEach(func() {
   314  						validation.Required = []string{"param"}
   315  					})
   316  
   317  					It("writes the String contexts code", func() {
   318  						err := writer.Execute(data)
   319  						Ω(err).ShouldNot(HaveOccurred())
   320  						b, err := ioutil.ReadFile(filename)
   321  						Ω(err).ShouldNot(HaveOccurred())
   322  						written := string(b)
   323  						Ω(written).ShouldNot(BeEmpty())
   324  						Ω(written).Should(ContainSubstring(strNonOptionalContext))
   325  						Ω(written).Should(ContainSubstring(strRequiredContextFactory))
   326  					})
   327  
   328  					Context("with a default value", func() {
   329  						BeforeEach(func() {
   330  							strParam.SetDefault("foo")
   331  						})
   332  
   333  						It("writes the integer contexts code", func() {
   334  							err := writer.Execute(data)
   335  							Ω(err).ShouldNot(HaveOccurred())
   336  							b, err := ioutil.ReadFile(filename)
   337  							Ω(err).ShouldNot(HaveOccurred())
   338  							written := string(b)
   339  							Ω(written).ShouldNot(BeEmpty())
   340  							Ω(written).Should(ContainSubstring(strNonOptionalContext))
   341  							Ω(written).Should(ContainSubstring(strDefaultContextFactory))
   342  						})
   343  					})
   344  				})
   345  			})
   346  
   347  			Context("with a number param", func() {
   348  				var (
   349  					numParam   *design.AttributeDefinition
   350  					dataType   design.Object
   351  					validation *dslengine.ValidationDefinition
   352  				)
   353  
   354  				BeforeEach(func() {
   355  					numParam = &design.AttributeDefinition{Type: design.Number}
   356  					dataType = design.Object{
   357  						"param": numParam,
   358  					}
   359  					validation = &dslengine.ValidationDefinition{}
   360  					params = &design.AttributeDefinition{
   361  						Type:       dataType,
   362  						Validation: validation,
   363  					}
   364  				})
   365  
   366  				It("writes the number contexts code", func() {
   367  					err := writer.Execute(data)
   368  					Ω(err).ShouldNot(HaveOccurred())
   369  					b, err := ioutil.ReadFile(filename)
   370  					Ω(err).ShouldNot(HaveOccurred())
   371  					written := string(b)
   372  					Ω(written).ShouldNot(BeEmpty())
   373  					Ω(written).Should(ContainSubstring(numContext))
   374  					Ω(written).Should(ContainSubstring(numContextFactory))
   375  				})
   376  
   377  				Context("with a default value", func() {
   378  					BeforeEach(func() {
   379  						numParam.SetDefault(2.3)
   380  					})
   381  
   382  					It("writes the number contexts code", func() {
   383  						err := writer.Execute(data)
   384  						Ω(err).ShouldNot(HaveOccurred())
   385  						b, err := ioutil.ReadFile(filename)
   386  						Ω(err).ShouldNot(HaveOccurred())
   387  						written := string(b)
   388  						Ω(written).ShouldNot(BeEmpty())
   389  						Ω(written).Should(ContainSubstring(numNonOptionalContext))
   390  						Ω(written).Should(ContainSubstring(numDefaultContextFactory))
   391  					})
   392  				})
   393  
   394  				Context("with required attribute", func() {
   395  					BeforeEach(func() {
   396  						validation.Required = []string{"param"}
   397  					})
   398  
   399  					It("writes the number contexts code", func() {
   400  						err := writer.Execute(data)
   401  						Ω(err).ShouldNot(HaveOccurred())
   402  						b, err := ioutil.ReadFile(filename)
   403  						Ω(err).ShouldNot(HaveOccurred())
   404  						written := string(b)
   405  						Ω(written).ShouldNot(BeEmpty())
   406  						Ω(written).Should(ContainSubstring(numNonOptionalContext))
   407  						Ω(written).Should(ContainSubstring(numRequiredContextFactory))
   408  					})
   409  
   410  					Context("with a default value", func() {
   411  						BeforeEach(func() {
   412  							numParam.SetDefault(2.3)
   413  						})
   414  
   415  						It("writes the number contexts code", func() {
   416  							err := writer.Execute(data)
   417  							Ω(err).ShouldNot(HaveOccurred())
   418  							b, err := ioutil.ReadFile(filename)
   419  							Ω(err).ShouldNot(HaveOccurred())
   420  							written := string(b)
   421  							Ω(written).ShouldNot(BeEmpty())
   422  							Ω(written).Should(ContainSubstring(numNonOptionalContext))
   423  							Ω(written).Should(ContainSubstring(numDefaultContextFactory))
   424  						})
   425  					})
   426  				})
   427  			})
   428  
   429  			Context("with a boolean param", func() {
   430  				var (
   431  					boolParam  *design.AttributeDefinition
   432  					dataType   design.Object
   433  					validation *dslengine.ValidationDefinition
   434  				)
   435  
   436  				BeforeEach(func() {
   437  					boolParam = &design.AttributeDefinition{Type: design.Boolean}
   438  					dataType = design.Object{
   439  						"param": boolParam,
   440  					}
   441  					validation = &dslengine.ValidationDefinition{}
   442  					params = &design.AttributeDefinition{
   443  						Type:       dataType,
   444  						Validation: validation,
   445  					}
   446  				})
   447  
   448  				It("writes the boolean contexts code", func() {
   449  					err := writer.Execute(data)
   450  					Ω(err).ShouldNot(HaveOccurred())
   451  					b, err := ioutil.ReadFile(filename)
   452  					Ω(err).ShouldNot(HaveOccurred())
   453  					written := string(b)
   454  					Ω(written).ShouldNot(BeEmpty())
   455  					Ω(written).Should(ContainSubstring(boolContext))
   456  					Ω(written).Should(ContainSubstring(boolContextFactory))
   457  				})
   458  
   459  				Context("with a default value", func() {
   460  					BeforeEach(func() {
   461  						boolParam.SetDefault(true)
   462  					})
   463  
   464  					It("writes the boolean contexts code", func() {
   465  						err := writer.Execute(data)
   466  						Ω(err).ShouldNot(HaveOccurred())
   467  						b, err := ioutil.ReadFile(filename)
   468  						Ω(err).ShouldNot(HaveOccurred())
   469  						written := string(b)
   470  						Ω(written).ShouldNot(BeEmpty())
   471  						Ω(written).Should(ContainSubstring(boolNonOptionalContext))
   472  						Ω(written).Should(ContainSubstring(boolDefaultContextFactory))
   473  					})
   474  				})
   475  
   476  				Context("with required attribute", func() {
   477  					BeforeEach(func() {
   478  						validation.Required = []string{"param"}
   479  					})
   480  
   481  					It("writes the boolean contexts code", func() {
   482  						err := writer.Execute(data)
   483  						Ω(err).ShouldNot(HaveOccurred())
   484  						b, err := ioutil.ReadFile(filename)
   485  						Ω(err).ShouldNot(HaveOccurred())
   486  						written := string(b)
   487  						Ω(written).ShouldNot(BeEmpty())
   488  						Ω(written).Should(ContainSubstring(boolNonOptionalContext))
   489  						Ω(written).Should(ContainSubstring(boolRequiredContextFactory))
   490  					})
   491  
   492  					Context("with a default value", func() {
   493  						BeforeEach(func() {
   494  							boolParam.SetDefault(true)
   495  						})
   496  
   497  						It("writes the boolean contexts code", func() {
   498  							err := writer.Execute(data)
   499  							Ω(err).ShouldNot(HaveOccurred())
   500  							b, err := ioutil.ReadFile(filename)
   501  							Ω(err).ShouldNot(HaveOccurred())
   502  							written := string(b)
   503  							Ω(written).ShouldNot(BeEmpty())
   504  							Ω(written).Should(ContainSubstring(boolNonOptionalContext))
   505  							Ω(written).Should(ContainSubstring(boolDefaultContextFactory))
   506  						})
   507  					})
   508  				})
   509  			})
   510  
   511  			Context("with a array param", func() {
   512  				var (
   513  					arrayParam *design.AttributeDefinition
   514  					dataType   design.Object
   515  					validation *dslengine.ValidationDefinition
   516  				)
   517  
   518  				BeforeEach(func() {
   519  					arrayParam = &design.AttributeDefinition{Type: &design.Array{ElemType: &design.AttributeDefinition{Type: design.String}}}
   520  					dataType = design.Object{
   521  						"param": arrayParam,
   522  					}
   523  					validation = &dslengine.ValidationDefinition{}
   524  					params = &design.AttributeDefinition{
   525  						Type:       dataType,
   526  						Validation: validation,
   527  					}
   528  				})
   529  
   530  				It("writes the array contexts code", func() {
   531  					err := writer.Execute(data)
   532  					Ω(err).ShouldNot(HaveOccurred())
   533  					b, err := ioutil.ReadFile(filename)
   534  					Ω(err).ShouldNot(HaveOccurred())
   535  					written := string(b)
   536  					Ω(written).ShouldNot(BeEmpty())
   537  					Ω(written).Should(ContainSubstring(arrayContext))
   538  					Ω(written).Should(ContainSubstring(arrayContextFactory))
   539  				})
   540  
   541  				Context("using a path param", func() {
   542  					BeforeEach(func() {
   543  						route := &design.RouteDefinition{Path: "/:param"}
   544  						routes = append(routes, route)
   545  					})
   546  
   547  					It("writes the array contexts code", func() {
   548  						err := writer.Execute(data)
   549  						Ω(err).ShouldNot(HaveOccurred())
   550  						b, err := ioutil.ReadFile(filename)
   551  						Ω(err).ShouldNot(HaveOccurred())
   552  						written := string(b)
   553  						Ω(written).ShouldNot(BeEmpty())
   554  						Ω(written).Should(ContainSubstring(arrayParamContextFactory))
   555  					})
   556  				})
   557  
   558  				Context("with a default value", func() {
   559  					BeforeEach(func() {
   560  						arrayParam.SetDefault([]interface{}{"foo", "bar", "baz"})
   561  					})
   562  
   563  					It("writes the array contexts code", func() {
   564  						err := writer.Execute(data)
   565  						Ω(err).ShouldNot(HaveOccurred())
   566  						b, err := ioutil.ReadFile(filename)
   567  						Ω(err).ShouldNot(HaveOccurred())
   568  						written := string(b)
   569  						Ω(written).ShouldNot(BeEmpty())
   570  						Ω(written).Should(ContainSubstring(arrayContext))
   571  						Ω(written).Should(ContainSubstring(arrayDefaultContextFactory))
   572  					})
   573  				})
   574  
   575  				Context("with required attribute", func() {
   576  					BeforeEach(func() {
   577  						validation.Required = []string{"param"}
   578  					})
   579  
   580  					It("writes the array contexts code", func() {
   581  						err := writer.Execute(data)
   582  						Ω(err).ShouldNot(HaveOccurred())
   583  						b, err := ioutil.ReadFile(filename)
   584  						Ω(err).ShouldNot(HaveOccurred())
   585  						written := string(b)
   586  						Ω(written).ShouldNot(BeEmpty())
   587  						Ω(written).Should(ContainSubstring(arrayContext))
   588  						Ω(written).Should(ContainSubstring(arrayRequiredContextFactory))
   589  					})
   590  
   591  					Context("with a default value", func() {
   592  						BeforeEach(func() {
   593  							arrayParam.SetDefault([]interface{}{"foo", "bar", "baz"})
   594  						})
   595  
   596  						It("writes the array contexts code", func() {
   597  							err := writer.Execute(data)
   598  							Ω(err).ShouldNot(HaveOccurred())
   599  							b, err := ioutil.ReadFile(filename)
   600  							Ω(err).ShouldNot(HaveOccurred())
   601  							written := string(b)
   602  							Ω(written).ShouldNot(BeEmpty())
   603  							Ω(written).Should(ContainSubstring(arrayContext))
   604  							Ω(written).Should(ContainSubstring(arrayDefaultContextFactory))
   605  						})
   606  					})
   607  				})
   608  			})
   609  
   610  			Context("with an int array param", func() {
   611  				var (
   612  					arrayParam *design.AttributeDefinition
   613  					dataType   design.Object
   614  					validation *dslengine.ValidationDefinition
   615  				)
   616  
   617  				BeforeEach(func() {
   618  					arrayParam = &design.AttributeDefinition{Type: &design.Array{ElemType: &design.AttributeDefinition{Type: design.Integer}}}
   619  					dataType = design.Object{
   620  						"param": arrayParam,
   621  					}
   622  					validation = &dslengine.ValidationDefinition{}
   623  					params = &design.AttributeDefinition{
   624  						Type:       dataType,
   625  						Validation: validation,
   626  					}
   627  				})
   628  
   629  				It("writes the array contexts code", func() {
   630  					err := writer.Execute(data)
   631  					Ω(err).ShouldNot(HaveOccurred())
   632  					b, err := ioutil.ReadFile(filename)
   633  					Ω(err).ShouldNot(HaveOccurred())
   634  					written := string(b)
   635  					Ω(written).ShouldNot(BeEmpty())
   636  					Ω(written).Should(ContainSubstring(intArrayContext))
   637  					Ω(written).Should(ContainSubstring(intArrayContextFactory))
   638  				})
   639  
   640  				Context("with a default value", func() {
   641  					BeforeEach(func() {
   642  						arrayParam.SetDefault([]interface{}{1, 1, 2, 3, 5, 8})
   643  					})
   644  
   645  					It("writes the array contexts code", func() {
   646  						err := writer.Execute(data)
   647  						Ω(err).ShouldNot(HaveOccurred())
   648  						b, err := ioutil.ReadFile(filename)
   649  						Ω(err).ShouldNot(HaveOccurred())
   650  						written := string(b)
   651  						Ω(written).ShouldNot(BeEmpty())
   652  						Ω(written).Should(ContainSubstring(intArrayContext))
   653  						Ω(written).Should(ContainSubstring(intArrayDefaultContextFactory))
   654  					})
   655  				})
   656  
   657  				Context("with required attribute", func() {
   658  					BeforeEach(func() {
   659  						validation.Required = []string{"param"}
   660  					})
   661  
   662  					It("writes the array contexts code", func() {
   663  						err := writer.Execute(data)
   664  						Ω(err).ShouldNot(HaveOccurred())
   665  						b, err := ioutil.ReadFile(filename)
   666  						Ω(err).ShouldNot(HaveOccurred())
   667  						written := string(b)
   668  						Ω(written).ShouldNot(BeEmpty())
   669  						Ω(written).Should(ContainSubstring(intArrayContext))
   670  						Ω(written).Should(ContainSubstring(intArrayRequiredContextFactory))
   671  					})
   672  
   673  					Context("with a default value", func() {
   674  						BeforeEach(func() {
   675  							arrayParam.SetDefault([]interface{}{1, 1, 2, 3, 5, 8})
   676  						})
   677  
   678  						It("writes the array contexts code", func() {
   679  							err := writer.Execute(data)
   680  							Ω(err).ShouldNot(HaveOccurred())
   681  							b, err := ioutil.ReadFile(filename)
   682  							Ω(err).ShouldNot(HaveOccurred())
   683  							written := string(b)
   684  							Ω(written).ShouldNot(BeEmpty())
   685  							Ω(written).Should(ContainSubstring(intArrayContext))
   686  							Ω(written).Should(ContainSubstring(intArrayDefaultContextFactory))
   687  						})
   688  					})
   689  				})
   690  			})
   691  
   692  			Context("with an param using a reserved keyword as name", func() {
   693  				BeforeEach(func() {
   694  					intParam := &design.AttributeDefinition{Type: design.Integer}
   695  					dataType := design.Object{
   696  						"int": intParam,
   697  					}
   698  					params = &design.AttributeDefinition{
   699  						Type: dataType,
   700  					}
   701  				})
   702  
   703  				It("writes the contexts code", func() {
   704  					err := writer.Execute(data)
   705  					Ω(err).ShouldNot(HaveOccurred())
   706  					b, err := ioutil.ReadFile(filename)
   707  					Ω(err).ShouldNot(HaveOccurred())
   708  					written := string(b)
   709  					Ω(written).ShouldNot(BeEmpty())
   710  					Ω(written).Should(ContainSubstring(resContext))
   711  					Ω(written).Should(ContainSubstring(resContextFactory))
   712  				})
   713  			})
   714  
   715  			Context("with a required param", func() {
   716  				BeforeEach(func() {
   717  					intParam := &design.AttributeDefinition{Type: design.Integer}
   718  					dataType := design.Object{
   719  						"int": intParam,
   720  					}
   721  					required := &dslengine.ValidationDefinition{
   722  						Required: []string{"int"},
   723  					}
   724  					params = &design.AttributeDefinition{
   725  						Type:       dataType,
   726  						Validation: required,
   727  					}
   728  				})
   729  
   730  				It("writes the contexts code", func() {
   731  					err := writer.Execute(data)
   732  					Ω(err).ShouldNot(HaveOccurred())
   733  					b, err := ioutil.ReadFile(filename)
   734  					Ω(err).ShouldNot(HaveOccurred())
   735  					written := string(b)
   736  					Ω(written).ShouldNot(BeEmpty())
   737  					Ω(written).Should(ContainSubstring(requiredContext))
   738  					Ω(written).Should(ContainSubstring(requiredContextFactory))
   739  				})
   740  			})
   741  
   742  			Context("with a custom name param", func() {
   743  				BeforeEach(func() {
   744  					intParam := &design.AttributeDefinition{
   745  						Type: design.Integer,
   746  						Metadata: dslengine.MetadataDefinition{
   747  							"struct:field:name": []string{"custom"},
   748  						},
   749  					}
   750  					dataType := design.Object{
   751  						"int": intParam,
   752  					}
   753  					params = &design.AttributeDefinition{
   754  						Type: dataType,
   755  					}
   756  				})
   757  
   758  				It("writes the contexts code", func() {
   759  					err := writer.Execute(data)
   760  					Ω(err).ShouldNot(HaveOccurred())
   761  					b, err := ioutil.ReadFile(filename)
   762  					Ω(err).ShouldNot(HaveOccurred())
   763  					written := string(b)
   764  					Ω(written).ShouldNot(BeEmpty())
   765  					Ω(written).Should(ContainSubstring(customContext))
   766  					Ω(written).Should(ContainSubstring(customContextFactory))
   767  				})
   768  			})
   769  
   770  			Context("with a string header", func() {
   771  				BeforeEach(func() {
   772  					strHeader := &design.AttributeDefinition{Type: design.String}
   773  					dataType := design.Object{
   774  						"Header": strHeader,
   775  					}
   776  					headers = &design.AttributeDefinition{
   777  						Type: dataType,
   778  					}
   779  				})
   780  
   781  				It("writes the contexts code", func() {
   782  					err := writer.Execute(data)
   783  					Ω(err).ShouldNot(HaveOccurred())
   784  					b, err := ioutil.ReadFile(filename)
   785  					Ω(err).ShouldNot(HaveOccurred())
   786  					written := string(b)
   787  					Ω(written).ShouldNot(BeEmpty())
   788  					Ω(written).Should(ContainSubstring(strHeaderContext))
   789  					Ω(written).Should(ContainSubstring(strHeaderContextFactory))
   790  				})
   791  			})
   792  
   793  			Context("with a string header and param with the same name", func() {
   794  				BeforeEach(func() {
   795  					str := &design.AttributeDefinition{Type: design.String}
   796  					dataType := design.Object{
   797  						"param": str,
   798  					}
   799  					params = &design.AttributeDefinition{
   800  						Type: dataType,
   801  					}
   802  					headers = &design.AttributeDefinition{
   803  						Type: dataType,
   804  					}
   805  				})
   806  
   807  				It("writes the contexts code", func() {
   808  					err := writer.Execute(data)
   809  					Ω(err).ShouldNot(HaveOccurred())
   810  					b, err := ioutil.ReadFile(filename)
   811  					Ω(err).ShouldNot(HaveOccurred())
   812  					written := string(b)
   813  					Ω(written).ShouldNot(BeEmpty())
   814  					Ω(written).Should(ContainSubstring(strContext))
   815  					Ω(written).Should(ContainSubstring(strHeaderParamContextFactory))
   816  				})
   817  			})
   818  
   819  			Context("with a simple payload", func() {
   820  				BeforeEach(func() {
   821  					design.Design = new(design.APIDefinition)
   822  					payload = &design.UserTypeDefinition{
   823  						AttributeDefinition: &design.AttributeDefinition{Type: design.String},
   824  						TypeName:            "ListBottlePayload",
   825  					}
   826  				})
   827  
   828  				It("writes the contexts code", func() {
   829  					err := writer.Execute(data)
   830  					Ω(err).ShouldNot(HaveOccurred())
   831  					b, err := ioutil.ReadFile(filename)
   832  					Ω(err).ShouldNot(HaveOccurred())
   833  					written := string(b)
   834  					Ω(written).ShouldNot(BeEmpty())
   835  					Ω(written).Should(ContainSubstring(payloadContext))
   836  					Ω(written).Should(ContainSubstring(payloadContextFactory))
   837  				})
   838  			})
   839  
   840  			Context("with a object payload", func() {
   841  				BeforeEach(func() {
   842  					design.Design = new(design.APIDefinition)
   843  					intParam := &design.AttributeDefinition{Type: design.Integer}
   844  					strParam := &design.AttributeDefinition{Type: design.String}
   845  					dataType := design.Object{
   846  						"int": intParam,
   847  						"str": strParam,
   848  					}
   849  					required := &dslengine.ValidationDefinition{
   850  						Required: []string{"int"},
   851  					}
   852  					payload = &design.UserTypeDefinition{
   853  						AttributeDefinition: &design.AttributeDefinition{
   854  							Type:       dataType,
   855  							Validation: required,
   856  						},
   857  						TypeName: "ListBottlePayload",
   858  					}
   859  				})
   860  
   861  				It("writes the contexts code", func() {
   862  					err := writer.Execute(data)
   863  					Ω(err).ShouldNot(HaveOccurred())
   864  					b, err := ioutil.ReadFile(filename)
   865  					Ω(err).ShouldNot(HaveOccurred())
   866  					written := string(b)
   867  					Ω(written).ShouldNot(BeEmpty())
   868  					Ω(written).Should(ContainSubstring(payloadObjContext))
   869  				})
   870  
   871  				var _ = Describe("IterateResponses", func() {
   872  					var resps []*design.ResponseDefinition
   873  					var testIt = func(r *design.ResponseDefinition) error {
   874  						resps = append(resps, r)
   875  						return nil
   876  					}
   877  					Context("with responses", func() {
   878  						BeforeEach(func() {
   879  							responses = map[string]*design.ResponseDefinition{
   880  								"OK":      {Status: 200},
   881  								"Created": {Status: 201},
   882  							}
   883  						})
   884  						It("iterates responses in order", func() {
   885  							data.IterateResponses(testIt)
   886  							Ω(resps).Should(Equal([]*design.ResponseDefinition{
   887  								responses["OK"],
   888  								responses["Created"],
   889  							}))
   890  						})
   891  					})
   892  				})
   893  			})
   894  		})
   895  	})
   896  })
   897  
   898  var _ = Describe("ControllersWriter", func() {
   899  	var writer *genapp.ControllersWriter
   900  	var workspace *codegen.Workspace
   901  	var filename string
   902  
   903  	BeforeEach(func() {
   904  		var err error
   905  		workspace, err = codegen.NewWorkspace("test")
   906  		Ω(err).ShouldNot(HaveOccurred())
   907  		pkg, err := workspace.NewPackage("controllers")
   908  		Ω(err).ShouldNot(HaveOccurred())
   909  		src, err := pkg.CreateSourceFile("test.go")
   910  		Ω(err).ShouldNot(HaveOccurred())
   911  		defer src.Close()
   912  		filename = src.Abs()
   913  	})
   914  
   915  	JustBeforeEach(func() {
   916  		var err error
   917  		writer, err = genapp.NewControllersWriter(filename)
   918  		Ω(err).ShouldNot(HaveOccurred())
   919  	})
   920  
   921  	AfterEach(func() {
   922  		workspace.Delete()
   923  	})
   924  
   925  	Context("correctly configured", func() {
   926  		BeforeEach(func() {
   927  			os.Create(filename)
   928  		})
   929  
   930  		Context("with file servers", func() {
   931  			requestPath := "/swagger.json"
   932  			filePath := "swagger/swagger.json"
   933  			var origins []*design.CORSDefinition
   934  			var preflightPaths []string
   935  
   936  			var data []*genapp.ControllerTemplateData
   937  
   938  			BeforeEach(func() {
   939  				origins = nil
   940  				preflightPaths = nil
   941  			})
   942  
   943  			JustBeforeEach(func() {
   944  				codegen.TempCount = 0
   945  				fileServer := &design.FileServerDefinition{
   946  					FilePath:    filePath,
   947  					RequestPath: requestPath,
   948  				}
   949  				d := &genapp.ControllerTemplateData{
   950  					API:            &design.APIDefinition{},
   951  					Origins:        origins,
   952  					PreflightPaths: preflightPaths,
   953  					Resource:       "Public",
   954  					FileServers:    []*design.FileServerDefinition{fileServer},
   955  				}
   956  				data = []*genapp.ControllerTemplateData{d}
   957  			})
   958  
   959  			It("writes the file server code", func() {
   960  				err := writer.Execute(data)
   961  				Ω(err).ShouldNot(HaveOccurred())
   962  				b, err := ioutil.ReadFile(filename)
   963  				Ω(err).ShouldNot(HaveOccurred())
   964  				written := string(b)
   965  				Ω(written).ShouldNot(BeEmpty())
   966  				Ω(written).Should(ContainSubstring(simpleFileServer))
   967  			})
   968  
   969  			Context("with CORS", func() {
   970  				BeforeEach(func() {
   971  					origins = []*design.CORSDefinition{
   972  						{
   973  							// NB: including backslash to ensure proper escaping
   974  							Origin:      "here.example.com",
   975  							Headers:     []string{"X-One", "X-Two"},
   976  							Methods:     []string{"GET", "POST"},
   977  							Exposed:     []string{"X-Three"},
   978  							Credentials: true,
   979  						},
   980  					}
   981  					preflightPaths = []string{"/public/star\\*star/*filepath"}
   982  				})
   983  
   984  				It("writes the OPTIONS handler code", func() {
   985  					err := writer.Execute(data)
   986  					Ω(err).ShouldNot(HaveOccurred())
   987  					b, err := ioutil.ReadFile(filename)
   988  					Ω(err).ShouldNot(HaveOccurred())
   989  					written := string(b)
   990  					Ω(written).ShouldNot(BeEmpty())
   991  					Ω(written).Should(ContainSubstring(fileServerOptionsHandler))
   992  				})
   993  			})
   994  		})
   995  
   996  		Context("with data", func() {
   997  			var multipart bool
   998  			var actions, verbs, paths, contexts, unmarshals []string
   999  			var payloads []*design.UserTypeDefinition
  1000  			var encoders, decoders []*genapp.EncoderTemplateData
  1001  			var origins []*design.CORSDefinition
  1002  
  1003  			var data []*genapp.ControllerTemplateData
  1004  
  1005  			BeforeEach(func() {
  1006  				multipart = false
  1007  				actions = nil
  1008  				verbs = nil
  1009  				paths = nil
  1010  				contexts = nil
  1011  				unmarshals = nil
  1012  				payloads = nil
  1013  				encoders = nil
  1014  				decoders = nil
  1015  				origins = nil
  1016  			})
  1017  
  1018  			JustBeforeEach(func() {
  1019  				codegen.TempCount = 0
  1020  				api := &design.APIDefinition{}
  1021  				d := &genapp.ControllerTemplateData{
  1022  					Resource: "Bottles",
  1023  					Origins:  origins,
  1024  				}
  1025  				as := make([]map[string]interface{}, len(actions))
  1026  				for i, a := range actions {
  1027  					var unmarshal string
  1028  					var payload *design.UserTypeDefinition
  1029  					if i < len(unmarshals) {
  1030  						unmarshal = unmarshals[i]
  1031  					}
  1032  					if i < len(payloads) {
  1033  						payload = payloads[i]
  1034  					}
  1035  					as[i] = map[string]interface{}{
  1036  						"Name":       codegen.Goify(a, true),
  1037  						"DesignName": a,
  1038  						"Routes": []*design.RouteDefinition{
  1039  							{
  1040  								Verb: verbs[i],
  1041  								Path: paths[i],
  1042  							}},
  1043  						"Context":          contexts[i],
  1044  						"Unmarshal":        unmarshal,
  1045  						"Payload":          payload,
  1046  						"PayloadMultipart": multipart,
  1047  					}
  1048  				}
  1049  				if len(as) > 0 {
  1050  					d.API = api
  1051  					d.Actions = as
  1052  					d.Encoders = encoders
  1053  					d.Decoders = decoders
  1054  					data = []*genapp.ControllerTemplateData{d}
  1055  				} else {
  1056  					data = nil
  1057  				}
  1058  			})
  1059  
  1060  			Context("with missing data", func() {
  1061  				It("returns an empty string", func() {
  1062  					err := writer.Execute(data)
  1063  					Ω(err).ShouldNot(HaveOccurred())
  1064  					b, err := ioutil.ReadFile(filename)
  1065  					Ω(err).ShouldNot(HaveOccurred())
  1066  					written := string(b)
  1067  					Ω(written).Should(BeEmpty())
  1068  				})
  1069  			})
  1070  
  1071  			Context("with a simple controller", func() {
  1072  				BeforeEach(func() {
  1073  					actions = []string{"list"}
  1074  					verbs = []string{"GET"}
  1075  					paths = []string{"/accounts/:accountID/bottles"}
  1076  					contexts = []string{"ListBottleContext"}
  1077  				})
  1078  
  1079  				It("writes the controller code", func() {
  1080  					err := writer.Execute(data)
  1081  					Ω(err).ShouldNot(HaveOccurred())
  1082  					b, err := ioutil.ReadFile(filename)
  1083  					Ω(err).ShouldNot(HaveOccurred())
  1084  					written := string(b)
  1085  					Ω(written).ShouldNot(BeEmpty())
  1086  					Ω(written).Should(ContainSubstring(simpleController))
  1087  					Ω(written).Should(ContainSubstring(simpleMount))
  1088  				})
  1089  			})
  1090  
  1091  			Context("with actions that take a payload", func() {
  1092  				BeforeEach(func() {
  1093  					actions = []string{"list"}
  1094  					verbs = []string{"GET"}
  1095  					paths = []string{"/accounts/:accountID/bottles"}
  1096  					contexts = []string{"ListBottleContext"}
  1097  					unmarshals = []string{"unmarshalListBottlePayload"}
  1098  					payloads = []*design.UserTypeDefinition{
  1099  						{
  1100  							TypeName: "ListBottlePayload",
  1101  							AttributeDefinition: &design.AttributeDefinition{
  1102  								Type: design.Object{
  1103  									"id": &design.AttributeDefinition{
  1104  										Type: design.String,
  1105  									},
  1106  								},
  1107  							},
  1108  						},
  1109  					}
  1110  				})
  1111  
  1112  				It("writes the payload unmarshal function", func() {
  1113  					err := writer.Execute(data)
  1114  					Ω(err).ShouldNot(HaveOccurred())
  1115  					b, err := ioutil.ReadFile(filename)
  1116  					Ω(err).ShouldNot(HaveOccurred())
  1117  					written := string(b)
  1118  					Ω(written).Should(ContainSubstring(payloadNoValidationsObjUnmarshal))
  1119  				})
  1120  			})
  1121  			Context("with actions that take a payload with a required validation", func() {
  1122  				BeforeEach(func() {
  1123  					actions = []string{"list"}
  1124  					required := &dslengine.ValidationDefinition{
  1125  						Required: []string{"id"},
  1126  					}
  1127  					verbs = []string{"GET"}
  1128  					paths = []string{"/accounts/:accountID/bottles"}
  1129  					contexts = []string{"ListBottleContext"}
  1130  					unmarshals = []string{"unmarshalListBottlePayload"}
  1131  					payloads = []*design.UserTypeDefinition{
  1132  						{
  1133  							TypeName: "ListBottlePayload",
  1134  							AttributeDefinition: &design.AttributeDefinition{
  1135  								Type: design.Object{
  1136  									"id": &design.AttributeDefinition{
  1137  										Type: design.String,
  1138  									},
  1139  								},
  1140  								Validation: required,
  1141  							},
  1142  						},
  1143  					}
  1144  				})
  1145  
  1146  				It("writes the payload unmarshal function", func() {
  1147  					err := writer.Execute(data)
  1148  					Ω(err).ShouldNot(HaveOccurred())
  1149  					b, err := ioutil.ReadFile(filename)
  1150  					Ω(err).ShouldNot(HaveOccurred())
  1151  					written := string(b)
  1152  					Ω(written).Should(ContainSubstring(payloadObjUnmarshal))
  1153  				})
  1154  			})
  1155  
  1156  			Context("with actions that take a multipart payload", func() {
  1157  				BeforeEach(func() {
  1158  					actions = []string{"list"}
  1159  					required := &dslengine.ValidationDefinition{
  1160  						Required: []string{"id"},
  1161  					}
  1162  					verbs = []string{"GET"}
  1163  					paths = []string{"/accounts/:accountID/bottles"}
  1164  					contexts = []string{"ListBottleContext"}
  1165  					unmarshals = []string{"unmarshalListBottlePayload"}
  1166  					payloads = []*design.UserTypeDefinition{
  1167  						{
  1168  							TypeName: "ListBottlePayload",
  1169  							AttributeDefinition: &design.AttributeDefinition{
  1170  								Type: design.Object{
  1171  									"id": &design.AttributeDefinition{
  1172  										Type: design.Integer,
  1173  									},
  1174  									"title": &design.AttributeDefinition{
  1175  										Type: design.String,
  1176  									},
  1177  									"icon": &design.AttributeDefinition{
  1178  										Type: design.File,
  1179  									},
  1180  									"flags": &design.AttributeDefinition{
  1181  										Type: &design.Array{
  1182  											ElemType: &design.AttributeDefinition{
  1183  												Type: design.Boolean,
  1184  											},
  1185  										},
  1186  									},
  1187  									"optionCodes": &design.AttributeDefinition{
  1188  										Type: &design.Array{
  1189  											ElemType: &design.AttributeDefinition{
  1190  												Type: design.Integer,
  1191  											},
  1192  										},
  1193  									},
  1194  									"ratios": &design.AttributeDefinition{
  1195  										Type: &design.Array{
  1196  											ElemType: &design.AttributeDefinition{
  1197  												Type: design.Number,
  1198  											},
  1199  										},
  1200  									},
  1201  									"commentLines": &design.AttributeDefinition{
  1202  										Type: &design.Array{
  1203  											ElemType: &design.AttributeDefinition{
  1204  												Type: design.String,
  1205  											},
  1206  										},
  1207  									},
  1208  									"objs": &design.AttributeDefinition{
  1209  										Type: &design.Array{
  1210  											ElemType: &design.AttributeDefinition{
  1211  												Type: &design.Object{},
  1212  											},
  1213  										},
  1214  									},
  1215  									"hashObjs": &design.AttributeDefinition{
  1216  										Type: &design.Array{
  1217  											ElemType: &design.AttributeDefinition{
  1218  												Type: &design.Hash{
  1219  													KeyType: &design.AttributeDefinition{
  1220  														Type: design.String,
  1221  													},
  1222  													ElemType: &design.AttributeDefinition{
  1223  														Type: &design.Array{
  1224  															ElemType: &design.AttributeDefinition{
  1225  																Type: design.String,
  1226  															},
  1227  														},
  1228  													},
  1229  												},
  1230  											},
  1231  										},
  1232  									},
  1233  								},
  1234  								Validation: required,
  1235  							},
  1236  						},
  1237  					}
  1238  					multipart = true
  1239  				})
  1240  
  1241  				It("writes the payload unmarshal function", func() {
  1242  					err := writer.Execute(data)
  1243  					Ω(err).ShouldNot(HaveOccurred())
  1244  					b, err := ioutil.ReadFile(filename)
  1245  					Ω(err).ShouldNot(HaveOccurred())
  1246  					written := string(b)
  1247  					Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshalID))
  1248  					Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshalTitle))
  1249  					Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshalIcon))
  1250  					Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshalFlags))
  1251  					Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshalOptionCodes))
  1252  					Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshalRatios))
  1253  					Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshalCommentLines))
  1254  					Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshalObjs))
  1255  					Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshalHashObjs))
  1256  				})
  1257  			})
  1258  
  1259  			Context("with multiple controllers", func() {
  1260  				BeforeEach(func() {
  1261  					actions = []string{"list", "show"}
  1262  					verbs = []string{"GET", "GET"}
  1263  					paths = []string{"/accounts/:accountID/bottles", "/accounts/:accountID/bottles/:id"}
  1264  					contexts = []string{"ListBottleContext", "ShowBottleContext"}
  1265  				})
  1266  
  1267  				It("writes the controllers code", func() {
  1268  					err := writer.Execute(data)
  1269  					Ω(err).ShouldNot(HaveOccurred())
  1270  					b, err := ioutil.ReadFile(filename)
  1271  					Ω(err).ShouldNot(HaveOccurred())
  1272  					written := string(b)
  1273  					Ω(written).ShouldNot(BeEmpty())
  1274  					Ω(written).Should(ContainSubstring(multiController))
  1275  					Ω(written).Should(ContainSubstring(multiMount))
  1276  				})
  1277  			})
  1278  
  1279  			Context("with encoder and decoder maps", func() {
  1280  				BeforeEach(func() {
  1281  					actions = []string{"list"}
  1282  					verbs = []string{"GET"}
  1283  					paths = []string{"/accounts/:accountID/bottles"}
  1284  					contexts = []string{"ListBottleContext"}
  1285  					encoders = []*genapp.EncoderTemplateData{
  1286  						{
  1287  							PackageName: "goa",
  1288  							Function:    "NewEncoder",
  1289  							MIMETypes:   []string{"application/json"},
  1290  						},
  1291  					}
  1292  					decoders = []*genapp.EncoderTemplateData{
  1293  						{
  1294  							PackageName: "goa",
  1295  							Function:    "NewDecoder",
  1296  							MIMETypes:   []string{"application/json"},
  1297  						},
  1298  					}
  1299  				})
  1300  
  1301  				It("writes the controllers code", func() {
  1302  					err := writer.Execute(data)
  1303  					Ω(err).ShouldNot(HaveOccurred())
  1304  					b, err := ioutil.ReadFile(filename)
  1305  					Ω(err).ShouldNot(HaveOccurred())
  1306  					written := string(b)
  1307  					Ω(written).ShouldNot(BeEmpty())
  1308  					Ω(written).Should(ContainSubstring(encoderController))
  1309  				})
  1310  			})
  1311  
  1312  			Context("with multiple origins", func() {
  1313  				BeforeEach(func() {
  1314  					actions = []string{"list"}
  1315  					verbs = []string{"GET"}
  1316  					paths = []string{"/accounts"}
  1317  					contexts = []string{"ListBottleContext"}
  1318  					origins = []*design.CORSDefinition{
  1319  						{
  1320  							Origin:      "here.example.com",
  1321  							Headers:     []string{"X-One", "X-Two"},
  1322  							Methods:     []string{"GET", "POST"},
  1323  							Exposed:     []string{"X-Three"},
  1324  							Credentials: true,
  1325  						},
  1326  						{
  1327  							Origin:  "there.example.com",
  1328  							Headers: []string{"*"},
  1329  							Methods: []string{"*"},
  1330  						},
  1331  					}
  1332  
  1333  				})
  1334  
  1335  				It("writes the controller code", func() {
  1336  					err := writer.Execute(data)
  1337  					Ω(err).ShouldNot(HaveOccurred())
  1338  					b, err := ioutil.ReadFile(filename)
  1339  					Ω(err).ShouldNot(HaveOccurred())
  1340  					written := string(b)
  1341  					Ω(written).ShouldNot(BeEmpty())
  1342  					Ω(written).Should(ContainSubstring(originsIntegration))
  1343  					Ω(written).Should(ContainSubstring(originsHandler))
  1344  				})
  1345  			})
  1346  
  1347  			Context("with regexp origins", func() {
  1348  				BeforeEach(func() {
  1349  					actions = []string{"list"}
  1350  					verbs = []string{"GET"}
  1351  					paths = []string{"/accounts"}
  1352  					contexts = []string{"ListBottleContext"}
  1353  					origins = []*design.CORSDefinition{
  1354  						{
  1355  							Origin:      "[here|there].example.com",
  1356  							Headers:     []string{"X-One", "X-Two"},
  1357  							Methods:     []string{"GET", "POST"},
  1358  							Exposed:     []string{"X-Three"},
  1359  							Credentials: true,
  1360  							Regexp:      true,
  1361  						},
  1362  						{
  1363  							Origin:  "there.example.com",
  1364  							Headers: []string{"*"},
  1365  							Methods: []string{"*"},
  1366  						},
  1367  					}
  1368  
  1369  				})
  1370  
  1371  				It("writes the controller code", func() {
  1372  					err := writer.Execute(data)
  1373  					Ω(err).ShouldNot(HaveOccurred())
  1374  					b, err := ioutil.ReadFile(filename)
  1375  					Ω(err).ShouldNot(HaveOccurred())
  1376  					written := string(b)
  1377  					Ω(written).ShouldNot(BeEmpty())
  1378  					Ω(written).Should(ContainSubstring(originsIntegration))
  1379  					Ω(written).Should(ContainSubstring(regexpOriginsHandler))
  1380  				})
  1381  			})
  1382  
  1383  		})
  1384  	})
  1385  })
  1386  
  1387  var _ = Describe("HrefWriter", func() {
  1388  	var writer *genapp.ResourcesWriter
  1389  	var workspace *codegen.Workspace
  1390  	var filename string
  1391  
  1392  	BeforeEach(func() {
  1393  		var err error
  1394  		workspace, err = codegen.NewWorkspace("test")
  1395  		Ω(err).ShouldNot(HaveOccurred())
  1396  		pkg, err := workspace.NewPackage("controllers")
  1397  		Ω(err).ShouldNot(HaveOccurred())
  1398  		src, err := pkg.CreateSourceFile("test.go")
  1399  		Ω(err).ShouldNot(HaveOccurred())
  1400  		defer src.Close()
  1401  		filename = src.Abs()
  1402  	})
  1403  
  1404  	JustBeforeEach(func() {
  1405  		var err error
  1406  		writer, err = genapp.NewResourcesWriter(filename)
  1407  		Ω(err).ShouldNot(HaveOccurred())
  1408  	})
  1409  
  1410  	AfterEach(func() {
  1411  		workspace.Delete()
  1412  	})
  1413  
  1414  	Context("correctly configured", func() {
  1415  		Context("with data", func() {
  1416  			var canoTemplate string
  1417  			var canoParams []string
  1418  			var mediaType *design.MediaTypeDefinition
  1419  
  1420  			var data *genapp.ResourceData
  1421  
  1422  			BeforeEach(func() {
  1423  				mediaType = nil
  1424  				canoTemplate = ""
  1425  				canoParams = nil
  1426  				data = nil
  1427  			})
  1428  
  1429  			JustBeforeEach(func() {
  1430  				data = &genapp.ResourceData{
  1431  					Name:              "Bottle",
  1432  					Identifier:        "vnd.acme.com/resources",
  1433  					Description:       "A bottle resource",
  1434  					Type:              mediaType,
  1435  					CanonicalTemplate: canoTemplate,
  1436  					CanonicalParams:   canoParams,
  1437  				}
  1438  			})
  1439  
  1440  			Context("with missing resource type definition", func() {
  1441  				It("does not return an error", func() {
  1442  					err := writer.Execute(data)
  1443  					Ω(err).ShouldNot(HaveOccurred())
  1444  				})
  1445  			})
  1446  
  1447  			Context("with a string resource", func() {
  1448  				BeforeEach(func() {
  1449  					attDef := &design.AttributeDefinition{
  1450  						Type: design.String,
  1451  					}
  1452  					mediaType = &design.MediaTypeDefinition{
  1453  						UserTypeDefinition: &design.UserTypeDefinition{
  1454  							AttributeDefinition: attDef,
  1455  							TypeName:            "Bottle",
  1456  						},
  1457  					}
  1458  				})
  1459  				It("does not return an error", func() {
  1460  					err := writer.Execute(data)
  1461  					Ω(err).ShouldNot(HaveOccurred())
  1462  				})
  1463  			})
  1464  
  1465  			Context("with a user type resource", func() {
  1466  				BeforeEach(func() {
  1467  					intParam := &design.AttributeDefinition{Type: design.Integer}
  1468  					strParam := &design.AttributeDefinition{Type: design.String}
  1469  					dataType := design.Object{
  1470  						"int": intParam,
  1471  						"str": strParam,
  1472  					}
  1473  					attDef := &design.AttributeDefinition{
  1474  						Type: dataType,
  1475  					}
  1476  					mediaType = &design.MediaTypeDefinition{
  1477  						UserTypeDefinition: &design.UserTypeDefinition{
  1478  							AttributeDefinition: attDef,
  1479  							TypeName:            "Bottle",
  1480  						},
  1481  					}
  1482  				})
  1483  
  1484  				Context("and a canonical action", func() {
  1485  					BeforeEach(func() {
  1486  						canoTemplate = "/bottles/%v"
  1487  						canoParams = []string{"id"}
  1488  					})
  1489  
  1490  					It("writes the href method", func() {
  1491  						err := writer.Execute(data)
  1492  						Ω(err).ShouldNot(HaveOccurred())
  1493  						b, err := ioutil.ReadFile(filename)
  1494  						Ω(err).ShouldNot(HaveOccurred())
  1495  						written := string(b)
  1496  						Ω(written).ShouldNot(BeEmpty())
  1497  						Ω(written).Should(ContainSubstring(simpleResourceHref))
  1498  					})
  1499  				})
  1500  
  1501  				Context("and a canonical action with no param", func() {
  1502  					BeforeEach(func() {
  1503  						canoTemplate = "/bottles"
  1504  					})
  1505  
  1506  					It("writes the href method", func() {
  1507  						err := writer.Execute(data)
  1508  						Ω(err).ShouldNot(HaveOccurred())
  1509  						b, err := ioutil.ReadFile(filename)
  1510  						Ω(err).ShouldNot(HaveOccurred())
  1511  						written := string(b)
  1512  						Ω(written).ShouldNot(BeEmpty())
  1513  						Ω(written).Should(ContainSubstring(noParamHref))
  1514  					})
  1515  				})
  1516  			})
  1517  		})
  1518  	})
  1519  })
  1520  
  1521  var _ = Describe("UserTypesWriter", func() {
  1522  	var writer *genapp.UserTypesWriter
  1523  	var workspace *codegen.Workspace
  1524  	var filename string
  1525  
  1526  	BeforeEach(func() {
  1527  		var err error
  1528  		workspace, err = codegen.NewWorkspace("test")
  1529  		Ω(err).ShouldNot(HaveOccurred())
  1530  		pkg, err := workspace.NewPackage("controllers")
  1531  		Ω(err).ShouldNot(HaveOccurred())
  1532  		src, err := pkg.CreateSourceFile("test.go")
  1533  		Ω(err).ShouldNot(HaveOccurred())
  1534  		defer src.Close()
  1535  		filename = src.Abs()
  1536  	})
  1537  
  1538  	JustBeforeEach(func() {
  1539  		var err error
  1540  		writer, err = genapp.NewUserTypesWriter(filename)
  1541  		Ω(err).ShouldNot(HaveOccurred())
  1542  	})
  1543  
  1544  	AfterEach(func() {
  1545  		workspace.Delete()
  1546  	})
  1547  
  1548  	Context("correctly configured", func() {
  1549  		Context("with data", func() {
  1550  			var data *design.UserTypeDefinition
  1551  			var attDef *design.AttributeDefinition
  1552  			var typeName string
  1553  
  1554  			BeforeEach(func() {
  1555  				data = nil
  1556  				attDef = nil
  1557  				typeName = ""
  1558  			})
  1559  
  1560  			JustBeforeEach(func() {
  1561  				data = &design.UserTypeDefinition{
  1562  					AttributeDefinition: attDef,
  1563  					TypeName:            typeName,
  1564  				}
  1565  			})
  1566  
  1567  			Context("with a simple user type", func() {
  1568  				BeforeEach(func() {
  1569  					attDef = &design.AttributeDefinition{
  1570  						Type: design.Object{
  1571  							"name": &design.AttributeDefinition{
  1572  								Type: design.String,
  1573  							},
  1574  						},
  1575  					}
  1576  					typeName = "SimplePayload"
  1577  				})
  1578  				It("writes the simple user type code", func() {
  1579  					err := writer.Execute(data)
  1580  					Ω(err).ShouldNot(HaveOccurred())
  1581  					b, err := ioutil.ReadFile(filename)
  1582  					Ω(err).ShouldNot(HaveOccurred())
  1583  					written := string(b)
  1584  					Ω(written).ShouldNot(BeEmpty())
  1585  					Ω(written).Should(ContainSubstring(simpleUserType))
  1586  				})
  1587  			})
  1588  
  1589  			Context("with a user type including hash", func() {
  1590  				BeforeEach(func() {
  1591  					attDef = &design.AttributeDefinition{
  1592  						Type: design.Object{
  1593  							"name": &design.AttributeDefinition{
  1594  								Type: design.String,
  1595  							},
  1596  							"misc": &design.AttributeDefinition{
  1597  								Type: &design.Hash{
  1598  									KeyType: &design.AttributeDefinition{
  1599  										Type: design.Integer,
  1600  									},
  1601  									ElemType: &design.AttributeDefinition{
  1602  										Type: &design.UserTypeDefinition{
  1603  											AttributeDefinition: &design.AttributeDefinition{
  1604  												Type: &design.UserTypeDefinition{
  1605  													AttributeDefinition: &design.AttributeDefinition{
  1606  														Type: design.Object{},
  1607  													},
  1608  													TypeName: "Misc",
  1609  												},
  1610  											},
  1611  											TypeName: "MiscPayload",
  1612  										},
  1613  									},
  1614  								},
  1615  							},
  1616  						},
  1617  					}
  1618  					typeName = "ComplexPayload"
  1619  				})
  1620  				It("writes the user type including hash", func() {
  1621  					err := writer.Execute(data)
  1622  					Ω(err).ShouldNot(HaveOccurred())
  1623  					b, err := ioutil.ReadFile(filename)
  1624  					Ω(err).ShouldNot(HaveOccurred())
  1625  					written := string(b)
  1626  					Ω(written).ShouldNot(BeEmpty())
  1627  					Ω(written).Should(ContainSubstring(userTypeIncludingHash))
  1628  				})
  1629  			})
  1630  		})
  1631  	})
  1632  })
  1633  
  1634  const (
  1635  	emptyContext = `
  1636  type ListBottleContext struct {
  1637  	context.Context
  1638  	*goa.ResponseData
  1639  	*goa.RequestData
  1640  }
  1641  `
  1642  
  1643  	emptyContextFactory = `
  1644  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1645  	var err error
  1646  	resp := goa.ContextResponse(ctx)
  1647  	resp.Service = service
  1648  	req := goa.ContextRequest(ctx)
  1649  	req.Request = r
  1650  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1651  	return &rctx, err
  1652  }
  1653  `
  1654  
  1655  	intContext = `
  1656  type ListBottleContext struct {
  1657  	context.Context
  1658  	*goa.ResponseData
  1659  	*goa.RequestData
  1660  	Param *int
  1661  }
  1662  `
  1663  
  1664  	intContextFactory = `
  1665  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1666  	var err error
  1667  	resp := goa.ContextResponse(ctx)
  1668  	resp.Service = service
  1669  	req := goa.ContextRequest(ctx)
  1670  	req.Request = r
  1671  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1672  	paramParam := req.Params["param"]
  1673  	if len(paramParam) > 0 {
  1674  		rawParam := paramParam[0]
  1675  		if param, err2 := strconv.Atoi(rawParam); err2 == nil {
  1676  			tmp2 := param
  1677  			tmp1 := &tmp2
  1678  			rctx.Param = tmp1
  1679  		} else {
  1680  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer"))
  1681  		}
  1682  	}
  1683  	return &rctx, err
  1684  }
  1685  `
  1686  
  1687  	intDefaultContext = `
  1688  type ListBottleContext struct {
  1689  	context.Context
  1690  	*goa.ResponseData
  1691  	*goa.RequestData
  1692  	Param int
  1693  }
  1694  `
  1695  
  1696  	intDefaultContextFactory = `
  1697  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1698  	var err error
  1699  	resp := goa.ContextResponse(ctx)
  1700  	resp.Service = service
  1701  	req := goa.ContextRequest(ctx)
  1702  	req.Request = r
  1703  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1704  	paramParam := req.Params["param"]
  1705  	if len(paramParam) == 0 {
  1706  		rctx.Param = 2
  1707  	} else {
  1708  		rawParam := paramParam[0]
  1709  		if param, err2 := strconv.Atoi(rawParam); err2 == nil {
  1710  			rctx.Param = param
  1711  		} else {
  1712  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer"))
  1713  		}
  1714  	}
  1715  	return &rctx, err
  1716  }
  1717  `
  1718  
  1719  	intRequiredDefaultContext = `
  1720  type ListBottleContext struct {
  1721  	context.Context
  1722  	*goa.ResponseData
  1723  	*goa.RequestData
  1724  	Param int
  1725  }
  1726  `
  1727  
  1728  	intRequiredDefaultContextFactory = `
  1729  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1730  	var err error
  1731  	resp := goa.ContextResponse(ctx)
  1732  	resp.Service = service
  1733  	req := goa.ContextRequest(ctx)
  1734  	req.Request = r
  1735  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1736  	paramParam := req.Params["param"]
  1737  	if len(paramParam) == 0 {
  1738  		rctx.Param = 2
  1739  	} else {
  1740  		rawParam := paramParam[0]
  1741  		if param, err2 := strconv.Atoi(rawParam); err2 == nil {
  1742  			rctx.Param = param
  1743  		} else {
  1744  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer"))
  1745  		}
  1746  	}
  1747  	return &rctx, err
  1748  }
  1749  `
  1750  
  1751  	intRequiredContext = `
  1752  type ListBottleContext struct {
  1753  	context.Context
  1754  	*goa.ResponseData
  1755  	*goa.RequestData
  1756  	Param int
  1757  }
  1758  `
  1759  	intRequiredContextFactory = `
  1760  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1761  	var err error
  1762  	resp := goa.ContextResponse(ctx)
  1763  	resp.Service = service
  1764  	req := goa.ContextRequest(ctx)
  1765  	req.Request = r
  1766  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1767  	paramParam := req.Params["param"]
  1768  	if len(paramParam) == 0 {
  1769  		err = goa.MergeErrors(err, goa.MissingParamError("param"))
  1770  	} else {
  1771  		rawParam := paramParam[0]
  1772  		if param, err2 := strconv.Atoi(rawParam); err2 == nil {
  1773  			rctx.Param = param
  1774  		} else {
  1775  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer"))
  1776  		}
  1777  	}
  1778  	return &rctx, err
  1779  }
  1780  `
  1781  
  1782  	strContext = `
  1783  type ListBottleContext struct {
  1784  	context.Context
  1785  	*goa.ResponseData
  1786  	*goa.RequestData
  1787  	Param *string
  1788  }
  1789  `
  1790  
  1791  	strContextFactory = `
  1792  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1793  	var err error
  1794  	resp := goa.ContextResponse(ctx)
  1795  	resp.Service = service
  1796  	req := goa.ContextRequest(ctx)
  1797  	req.Request = r
  1798  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1799  	paramParam := req.Params["param"]
  1800  	if len(paramParam) > 0 {
  1801  		rawParam := paramParam[0]
  1802  		rctx.Param = &rawParam
  1803  	}
  1804  	return &rctx, err
  1805  }
  1806  `
  1807  
  1808  	strNonOptionalContext = `
  1809  type ListBottleContext struct {
  1810  	context.Context
  1811  	*goa.ResponseData
  1812  	*goa.RequestData
  1813  	Param string
  1814  }
  1815  `
  1816  
  1817  	strDefaultContextFactory = `
  1818  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1819  	var err error
  1820  	resp := goa.ContextResponse(ctx)
  1821  	resp.Service = service
  1822  	req := goa.ContextRequest(ctx)
  1823  	req.Request = r
  1824  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1825  	paramParam := req.Params["param"]
  1826  	if len(paramParam) == 0 {
  1827  		rctx.Param = "foo"
  1828  	} else {
  1829  		rawParam := paramParam[0]
  1830  		rctx.Param = rawParam
  1831  	}
  1832  	return &rctx, err
  1833  }
  1834  `
  1835  
  1836  	strRequiredContextFactory = `
  1837  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1838  	var err error
  1839  	resp := goa.ContextResponse(ctx)
  1840  	resp.Service = service
  1841  	req := goa.ContextRequest(ctx)
  1842  	req.Request = r
  1843  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1844  	paramParam := req.Params["param"]
  1845  	if len(paramParam) == 0 {
  1846  		err = goa.MergeErrors(err, goa.MissingParamError("param"))
  1847  	} else {
  1848  		rawParam := paramParam[0]
  1849  		rctx.Param = rawParam
  1850  	}
  1851  	return &rctx, err
  1852  }
  1853  `
  1854  
  1855  	strHeaderContext = `
  1856  type ListBottleContext struct {
  1857  	context.Context
  1858  	*goa.ResponseData
  1859  	*goa.RequestData
  1860  	Header *string
  1861  }
  1862  `
  1863  
  1864  	strHeaderContextFactory = `
  1865  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1866  	var err error
  1867  	resp := goa.ContextResponse(ctx)
  1868  	resp.Service = service
  1869  	req := goa.ContextRequest(ctx)
  1870  	req.Request = r
  1871  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1872  	headerHeader := req.Header["Header"]
  1873  	if len(headerHeader) > 0 {
  1874  		rawHeader := headerHeader[0]
  1875  		req.Params["Header"] = []string{rawHeader}
  1876  		rctx.Header = &rawHeader
  1877  	}
  1878  	return &rctx, err
  1879  }
  1880  `
  1881  
  1882  	strHeaderParamContextFactory = `
  1883  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1884  	var err error
  1885  	resp := goa.ContextResponse(ctx)
  1886  	resp.Service = service
  1887  	req := goa.ContextRequest(ctx)
  1888  	req.Request = r
  1889  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1890  	headerParam := req.Header["Param"]
  1891  	if len(headerParam) > 0 {
  1892  		rawParam := headerParam[0]
  1893  		req.Params["param"] = []string{rawParam}
  1894  		rctx.Param = &rawParam
  1895  	}
  1896  	paramParam := req.Params["param"]
  1897  	if len(paramParam) > 0 {
  1898  		rawParam := paramParam[0]
  1899  		rctx.Param = &rawParam
  1900  	}
  1901  	return &rctx, err
  1902  }
  1903  `
  1904  
  1905  	numContext = `
  1906  type ListBottleContext struct {
  1907  	context.Context
  1908  	*goa.ResponseData
  1909  	*goa.RequestData
  1910  	Param *float64
  1911  }
  1912  `
  1913  
  1914  	numContextFactory = `
  1915  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1916  	var err error
  1917  	resp := goa.ContextResponse(ctx)
  1918  	resp.Service = service
  1919  	req := goa.ContextRequest(ctx)
  1920  	req.Request = r
  1921  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1922  	paramParam := req.Params["param"]
  1923  	if len(paramParam) > 0 {
  1924  		rawParam := paramParam[0]
  1925  		if param, err2 := strconv.ParseFloat(rawParam, 64); err2 == nil {
  1926  			tmp1 := &param
  1927  			rctx.Param = tmp1
  1928  		} else {
  1929  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "number"))
  1930  		}
  1931  	}
  1932  	return &rctx, err
  1933  }
  1934  `
  1935  
  1936  	numNonOptionalContext = `
  1937  type ListBottleContext struct {
  1938  	context.Context
  1939  	*goa.ResponseData
  1940  	*goa.RequestData
  1941  	Param float64
  1942  }
  1943  `
  1944  
  1945  	numDefaultContextFactory = `
  1946  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1947  	var err error
  1948  	resp := goa.ContextResponse(ctx)
  1949  	resp.Service = service
  1950  	req := goa.ContextRequest(ctx)
  1951  	req.Request = r
  1952  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1953  	paramParam := req.Params["param"]
  1954  	if len(paramParam) == 0 {
  1955  		rctx.Param = 2.300000
  1956  	} else {
  1957  		rawParam := paramParam[0]
  1958  		if param, err2 := strconv.ParseFloat(rawParam, 64); err2 == nil {
  1959  			rctx.Param = param
  1960  		} else {
  1961  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "number"))
  1962  		}
  1963  	}
  1964  	return &rctx, err
  1965  }
  1966  `
  1967  
  1968  	numRequiredContextFactory = `
  1969  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  1970  	var err error
  1971  	resp := goa.ContextResponse(ctx)
  1972  	resp.Service = service
  1973  	req := goa.ContextRequest(ctx)
  1974  	req.Request = r
  1975  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  1976  	paramParam := req.Params["param"]
  1977  	if len(paramParam) == 0 {
  1978  		err = goa.MergeErrors(err, goa.MissingParamError("param"))
  1979  	} else {
  1980  		rawParam := paramParam[0]
  1981  		if param, err2 := strconv.ParseFloat(rawParam, 64); err2 == nil {
  1982  			rctx.Param = param
  1983  		} else {
  1984  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "number"))
  1985  		}
  1986  	}
  1987  	return &rctx, err
  1988  }
  1989  `
  1990  
  1991  	boolContext = `
  1992  type ListBottleContext struct {
  1993  	context.Context
  1994  	*goa.ResponseData
  1995  	*goa.RequestData
  1996  	Param *bool
  1997  }
  1998  `
  1999  
  2000  	boolContextFactory = `
  2001  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2002  	var err error
  2003  	resp := goa.ContextResponse(ctx)
  2004  	resp.Service = service
  2005  	req := goa.ContextRequest(ctx)
  2006  	req.Request = r
  2007  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2008  	paramParam := req.Params["param"]
  2009  	if len(paramParam) > 0 {
  2010  		rawParam := paramParam[0]
  2011  		if param, err2 := strconv.ParseBool(rawParam); err2 == nil {
  2012  			tmp1 := &param
  2013  			rctx.Param = tmp1
  2014  		} else {
  2015  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "boolean"))
  2016  		}
  2017  	}
  2018  	return &rctx, err
  2019  }
  2020  `
  2021  
  2022  	boolNonOptionalContext = `
  2023  type ListBottleContext struct {
  2024  	context.Context
  2025  	*goa.ResponseData
  2026  	*goa.RequestData
  2027  	Param bool
  2028  }
  2029  `
  2030  
  2031  	boolDefaultContextFactory = `
  2032  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2033  	var err error
  2034  	resp := goa.ContextResponse(ctx)
  2035  	resp.Service = service
  2036  	req := goa.ContextRequest(ctx)
  2037  	req.Request = r
  2038  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2039  	paramParam := req.Params["param"]
  2040  	if len(paramParam) == 0 {
  2041  		rctx.Param = true
  2042  	} else {
  2043  		rawParam := paramParam[0]
  2044  		if param, err2 := strconv.ParseBool(rawParam); err2 == nil {
  2045  			rctx.Param = param
  2046  		} else {
  2047  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "boolean"))
  2048  		}
  2049  	}
  2050  	return &rctx, err
  2051  }
  2052  `
  2053  
  2054  	boolRequiredContextFactory = `
  2055  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2056  	var err error
  2057  	resp := goa.ContextResponse(ctx)
  2058  	resp.Service = service
  2059  	req := goa.ContextRequest(ctx)
  2060  	req.Request = r
  2061  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2062  	paramParam := req.Params["param"]
  2063  	if len(paramParam) == 0 {
  2064  		err = goa.MergeErrors(err, goa.MissingParamError("param"))
  2065  	} else {
  2066  		rawParam := paramParam[0]
  2067  		if param, err2 := strconv.ParseBool(rawParam); err2 == nil {
  2068  			rctx.Param = param
  2069  		} else {
  2070  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "boolean"))
  2071  		}
  2072  	}
  2073  	return &rctx, err
  2074  }
  2075  `
  2076  
  2077  	arrayContext = `
  2078  type ListBottleContext struct {
  2079  	context.Context
  2080  	*goa.ResponseData
  2081  	*goa.RequestData
  2082  	Param []string
  2083  }
  2084  `
  2085  
  2086  	arrayContextFactory = `
  2087  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2088  	var err error
  2089  	resp := goa.ContextResponse(ctx)
  2090  	resp.Service = service
  2091  	req := goa.ContextRequest(ctx)
  2092  	req.Request = r
  2093  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2094  	paramParam := req.Params["param"]
  2095  	if len(paramParam) > 0 {
  2096  		params := paramParam
  2097  		rctx.Param = params
  2098  	}
  2099  	return &rctx, err
  2100  }
  2101  `
  2102  
  2103  	arrayParamContextFactory = `
  2104  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2105  	var err error
  2106  	resp := goa.ContextResponse(ctx)
  2107  	resp.Service = service
  2108  	req := goa.ContextRequest(ctx)
  2109  	req.Request = r
  2110  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2111  	paramParam := req.Params["param"]
  2112  	if len(paramParam) > 0 {
  2113  		params := paramParam
  2114  		rctx.Param = params
  2115  	}
  2116  	return &rctx, err
  2117  }
  2118  `
  2119  
  2120  	arrayDefaultContextFactory = `
  2121  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2122  	var err error
  2123  	resp := goa.ContextResponse(ctx)
  2124  	resp.Service = service
  2125  	req := goa.ContextRequest(ctx)
  2126  	req.Request = r
  2127  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2128  	paramParam := req.Params["param"]
  2129  	if len(paramParam) == 0 {
  2130  		rctx.Param = []string{"foo", "bar", "baz"}
  2131  	} else {
  2132  		params := paramParam
  2133  		rctx.Param = params
  2134  	}
  2135  	return &rctx, err
  2136  }
  2137  `
  2138  
  2139  	arrayRequiredContextFactory = `
  2140  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2141  	var err error
  2142  	resp := goa.ContextResponse(ctx)
  2143  	resp.Service = service
  2144  	req := goa.ContextRequest(ctx)
  2145  	req.Request = r
  2146  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2147  	paramParam := req.Params["param"]
  2148  	if len(paramParam) == 0 {
  2149  		err = goa.MergeErrors(err, goa.MissingParamError("param"))
  2150  	} else {
  2151  		params := paramParam
  2152  		rctx.Param = params
  2153  	}
  2154  	return &rctx, err
  2155  }
  2156  `
  2157  
  2158  	intArrayContext = `
  2159  type ListBottleContext struct {
  2160  	context.Context
  2161  	*goa.ResponseData
  2162  	*goa.RequestData
  2163  	Param []int
  2164  }
  2165  `
  2166  
  2167  	intArrayContextFactory = `
  2168  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2169  	var err error
  2170  	resp := goa.ContextResponse(ctx)
  2171  	resp.Service = service
  2172  	req := goa.ContextRequest(ctx)
  2173  	req.Request = r
  2174  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2175  	paramParam := req.Params["param"]
  2176  	if len(paramParam) > 0 {
  2177  		params := make([]int, len(paramParam))
  2178  		for i, rawParam := range paramParam {
  2179  			if param, err2 := strconv.Atoi(rawParam); err2 == nil {
  2180  				params[i] = param
  2181  			} else {
  2182  				err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer"))
  2183  			}
  2184  		}
  2185  		rctx.Param = params
  2186  	}
  2187  	return &rctx, err
  2188  }
  2189  `
  2190  
  2191  	intArrayDefaultContextFactory = `
  2192  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2193  	var err error
  2194  	resp := goa.ContextResponse(ctx)
  2195  	resp.Service = service
  2196  	req := goa.ContextRequest(ctx)
  2197  	req.Request = r
  2198  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2199  	paramParam := req.Params["param"]
  2200  	if len(paramParam) == 0 {
  2201  		rctx.Param = []int{1, 1, 2, 3, 5, 8}
  2202  	} else {
  2203  		params := make([]int, len(paramParam))
  2204  		for i, rawParam := range paramParam {
  2205  			if param, err2 := strconv.Atoi(rawParam); err2 == nil {
  2206  				params[i] = param
  2207  			} else {
  2208  				err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer"))
  2209  			}
  2210  		}
  2211  		rctx.Param = params
  2212  	}
  2213  	return &rctx, err
  2214  }
  2215  `
  2216  
  2217  	intArrayRequiredContextFactory = `
  2218  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2219  	var err error
  2220  	resp := goa.ContextResponse(ctx)
  2221  	resp.Service = service
  2222  	req := goa.ContextRequest(ctx)
  2223  	req.Request = r
  2224  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2225  	paramParam := req.Params["param"]
  2226  	if len(paramParam) == 0 {
  2227  		err = goa.MergeErrors(err, goa.MissingParamError("param"))
  2228  	} else {
  2229  		params := make([]int, len(paramParam))
  2230  		for i, rawParam := range paramParam {
  2231  			if param, err2 := strconv.Atoi(rawParam); err2 == nil {
  2232  				params[i] = param
  2233  			} else {
  2234  				err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer"))
  2235  			}
  2236  		}
  2237  		rctx.Param = params
  2238  	}
  2239  	return &rctx, err
  2240  }
  2241  `
  2242  
  2243  	resContext = `
  2244  type ListBottleContext struct {
  2245  	context.Context
  2246  	*goa.ResponseData
  2247  	*goa.RequestData
  2248  	Int *int
  2249  }
  2250  `
  2251  
  2252  	resContextFactory = `
  2253  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2254  	var err error
  2255  	resp := goa.ContextResponse(ctx)
  2256  	resp.Service = service
  2257  	req := goa.ContextRequest(ctx)
  2258  	req.Request = r
  2259  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2260  	paramInt := req.Params["int"]
  2261  	if len(paramInt) > 0 {
  2262  		rawInt := paramInt[0]
  2263  		if int_, err2 := strconv.Atoi(rawInt); err2 == nil {
  2264  			tmp2 := int_
  2265  			tmp1 := &tmp2
  2266  			rctx.Int = tmp1
  2267  		} else {
  2268  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("int", rawInt, "integer"))
  2269  		}
  2270  	}
  2271  	return &rctx, err
  2272  }
  2273  `
  2274  
  2275  	requiredContext = `
  2276  type ListBottleContext struct {
  2277  	context.Context
  2278  	*goa.ResponseData
  2279  	*goa.RequestData
  2280  	Int int
  2281  }
  2282  `
  2283  
  2284  	requiredContextFactory = `
  2285  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2286  	var err error
  2287  	resp := goa.ContextResponse(ctx)
  2288  	resp.Service = service
  2289  	req := goa.ContextRequest(ctx)
  2290  	req.Request = r
  2291  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2292  	paramInt := req.Params["int"]
  2293  	if len(paramInt) == 0 {
  2294  		err = goa.MergeErrors(err, goa.MissingParamError("int"))
  2295  	} else {
  2296  		rawInt := paramInt[0]
  2297  		if int_, err2 := strconv.Atoi(rawInt); err2 == nil {
  2298  			rctx.Int = int_
  2299  		} else {
  2300  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("int", rawInt, "integer"))
  2301  		}
  2302  	}
  2303  	return &rctx, err
  2304  }
  2305  `
  2306  
  2307  	customContext = `
  2308  type ListBottleContext struct {
  2309  	context.Context
  2310  	*goa.ResponseData
  2311  	*goa.RequestData
  2312  	Custom *int
  2313  }
  2314  `
  2315  
  2316  	customContextFactory = `
  2317  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2318  	var err error
  2319  	resp := goa.ContextResponse(ctx)
  2320  	resp.Service = service
  2321  	req := goa.ContextRequest(ctx)
  2322  	req.Request = r
  2323  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2324  	paramInt := req.Params["int"]
  2325  	if len(paramInt) > 0 {
  2326  		rawInt := paramInt[0]
  2327  		if int_, err2 := strconv.Atoi(rawInt); err2 == nil {
  2328  			tmp2 := int_
  2329  			tmp1 := &tmp2
  2330  			rctx.Custom = tmp1
  2331  		} else {
  2332  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("int", rawInt, "integer"))
  2333  		}
  2334  	}
  2335  	return &rctx, err
  2336  }
  2337  `
  2338  
  2339  	payloadContext = `
  2340  type ListBottleContext struct {
  2341  	context.Context
  2342  	*goa.ResponseData
  2343  	*goa.RequestData
  2344  	Payload ListBottlePayload
  2345  }
  2346  `
  2347  
  2348  	payloadContextFactory = `
  2349  func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) {
  2350  	var err error
  2351  	resp := goa.ContextResponse(ctx)
  2352  	resp.Service = service
  2353  	req := goa.ContextRequest(ctx)
  2354  	req.Request = r
  2355  	rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req}
  2356  	return &rctx, err
  2357  }
  2358  `
  2359  	payloadObjContext = `
  2360  type ListBottleContext struct {
  2361  	context.Context
  2362  	*goa.ResponseData
  2363  	*goa.RequestData
  2364  	Payload *ListBottlePayload
  2365  }
  2366  `
  2367  
  2368  	payloadObjUnmarshal = `
  2369  func unmarshalListBottlePayload(ctx context.Context, service *goa.Service, req *http.Request) error {
  2370  	payload := &listBottlePayload{}
  2371  	if err := service.DecodeRequest(req, payload); err != nil {
  2372  		return err
  2373  	}
  2374  	if err := payload.Validate(); err != nil {
  2375  		// Initialize payload with private data structure so it can be logged
  2376  		goa.ContextRequest(ctx).Payload = payload
  2377  		return err
  2378  	}
  2379  	goa.ContextRequest(ctx).Payload = payload.Publicize()
  2380  	return nil
  2381  }
  2382  `
  2383  
  2384  	payloadMultipartObjUnmarshalID = `
  2385  	rawID := req.FormValue("id")
  2386  	if id, err2 := strconv.Atoi(rawID); err2 == nil {
  2387  		tmp2 := id
  2388  		tmp1 := &tmp2
  2389  		payload.ID = tmp1
  2390  	} else {
  2391  		err = goa.MergeErrors(err, goa.InvalidParamTypeError("id", rawID, "integer"))
  2392  	}`
  2393  
  2394  	payloadMultipartObjUnmarshalTitle = `
  2395  	rawTitle := req.FormValue("title")
  2396  	payload.Title = &rawTitle`
  2397  
  2398  	payloadMultipartObjUnmarshalIcon = `
  2399  	_, rawIcon, err2 := req.FormFile("icon")
  2400  	if err2 == nil {
  2401  		payload.Icon = rawIcon
  2402  	} else {
  2403  		err = goa.MergeErrors(err, goa.InvalidParamTypeError("icon", "icon", "file"))
  2404  	}`
  2405  
  2406  	payloadMultipartObjUnmarshalCommentLines = `
  2407  	rawCommentLines := req.Form["commentLines[]"]
  2408  	tmpCommentLines := make([]string, len(rawCommentLines))
  2409  	for i := 0; i < len(rawCommentLines); i++ {
  2410  		tmp := rawCommentLines[i]
  2411  		tmpCommentLines[i] = tmp
  2412  	}
  2413  	payload.CommentLines = tmpCommentLines`
  2414  
  2415  	payloadMultipartObjUnmarshalFlags = `
  2416  	rawFlags := req.Form["flags[]"]
  2417  	tmpFlags := make([]bool, len(rawFlags))
  2418  	for i := 0; i < len(rawFlags); i++ {
  2419  		tmp, err2 := strconv.ParseBool(rawFlags[i])
  2420  		if err2 != nil {
  2421  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("flags", rawFlags, "[]bool"))
  2422  			break
  2423  		}
  2424  		tmpFlags[i] = tmp
  2425  	}
  2426  	payload.Flags = tmpFlags`
  2427  
  2428  	payloadMultipartObjUnmarshalOptionCodes = `
  2429  	rawOptionCodes := req.Form["optionCodes[]"]
  2430  	tmpOptionCodes := make([]int, len(rawOptionCodes))
  2431  	for i := 0; i < len(rawOptionCodes); i++ {
  2432  		tmp, err2 := strconv.Atoi(rawOptionCodes[i])
  2433  		if err2 != nil {
  2434  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("optionCodes", rawOptionCodes, "[]int"))
  2435  			break
  2436  		}
  2437  		tmpOptionCodes[i] = tmp
  2438  	}
  2439  	payload.OptionCodes = tmpOptionCodes`
  2440  
  2441  	payloadMultipartObjUnmarshalRatios = `
  2442  	rawRatios := req.Form["ratios[]"]
  2443  	tmpRatios := make([]float, len(rawRatios))
  2444  	for i := 0; i < len(rawRatios); i++ {
  2445  		tmp, err2 := strconv.ParseFloat(rawRatios[i])
  2446  		if err2 != nil {
  2447  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("ratios", rawRatios, "[]float"))
  2448  			break
  2449  		}
  2450  		tmpRatios[i] = tmp
  2451  	}
  2452  	payload.Ratios = tmpRatios`
  2453  
  2454  	payloadMultipartObjUnmarshalObjs = `
  2455  	rawObjs := req.Form["objs[]"]
  2456  	tmpObjs := make([]interface{}, len(rawObjs))
  2457  	for i := 0; i < len(rawObjs); i++ {
  2458  		tmp, err2 := (interface{})(nil), (error)(nil)
  2459  		if err2 != nil {
  2460  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("objs", rawObjs, "[]interface{}"))
  2461  			break
  2462  		}
  2463  		tmpObjs[i] = tmp
  2464  	}
  2465  	payload.Objs = tmpObjs`
  2466  
  2467  	payloadMultipartObjUnmarshalHashObjs = `
  2468  	rawHashObjs := req.Form["hashObjs[]"]
  2469  	tmpHashObjs := make([]map[string][]string, len(rawHashObjs))
  2470  	for i := 0; i < len(rawHashObjs); i++ {
  2471  		tmp, err2 := map[string][]string{}, (error)(nil)
  2472  		if err2 != nil {
  2473  			err = goa.MergeErrors(err, goa.InvalidParamTypeError("hashObjs", rawHashObjs, "[]map[string][]string"))
  2474  			break
  2475  		}
  2476  		tmpHashObjs[i] = tmp
  2477  	}
  2478  	payload.HashObjs = tmpHashObjs`
  2479  
  2480  	payloadNoValidationsObjUnmarshal = `
  2481  func unmarshalListBottlePayload(ctx context.Context, service *goa.Service, req *http.Request) error {
  2482  	payload := &listBottlePayload{}
  2483  	if err := service.DecodeRequest(req, payload); err != nil {
  2484  		return err
  2485  	}
  2486  	goa.ContextRequest(ctx).Payload = payload.Publicize()
  2487  	return nil
  2488  }
  2489  `
  2490  
  2491  	simpleFileServer = `// PublicController is the controller interface for the Public actions.
  2492  type PublicController interface {
  2493  	goa.Muxer
  2494  	goa.FileServer
  2495  }
  2496  `
  2497  
  2498  	fileServerOptionsHandler = `service.Mux.Handle("OPTIONS", "/public/star\\*star/*filepath", ctrl.MuxHandler("preflight", handlePublicOrigin(cors.HandlePreflight()), nil))`
  2499  
  2500  	simpleController = `// BottlesController is the controller interface for the Bottles actions.
  2501  type BottlesController interface {
  2502  	goa.Muxer
  2503  	List(*ListBottleContext) error
  2504  }
  2505  `
  2506  
  2507  	originsIntegration = `}
  2508  	h = handleBottlesOrigin(h)
  2509  	service.Mux.Handle`
  2510  
  2511  	originsHandler = `// handleBottlesOrigin applies the CORS response headers corresponding to the origin.
  2512  func handleBottlesOrigin(h goa.Handler) goa.Handler {
  2513  
  2514  	return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
  2515  		origin := req.Header.Get("Origin")
  2516  		if origin == "" {
  2517  			// Not a CORS request
  2518  			return h(ctx, rw, req)
  2519  		}
  2520  		if cors.MatchOrigin(origin, "here.example.com") {
  2521  			ctx = goa.WithLogContext(ctx, "origin", origin)
  2522  			rw.Header().Set("Access-Control-Allow-Origin", origin)
  2523  			rw.Header().Set("Vary", "Origin")
  2524  			rw.Header().Set("Access-Control-Expose-Headers", "X-Three")
  2525  			rw.Header().Set("Access-Control-Allow-Credentials", "true")
  2526  			if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" {
  2527  				// We are handling a preflight request
  2528  				rw.Header().Set("Access-Control-Allow-Methods", "GET, POST")
  2529  				rw.Header().Set("Access-Control-Allow-Headers", "X-One, X-Two")
  2530  			}
  2531  			return h(ctx, rw, req)
  2532  		}
  2533  		if cors.MatchOrigin(origin, "there.example.com") {
  2534  			ctx = goa.WithLogContext(ctx, "origin", origin)
  2535  			rw.Header().Set("Access-Control-Allow-Origin", origin)
  2536  			rw.Header().Set("Vary", "Origin")
  2537  			rw.Header().Set("Access-Control-Allow-Credentials", "false")
  2538  			if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" {
  2539  				// We are handling a preflight request
  2540  				rw.Header().Set("Access-Control-Allow-Methods", "*")
  2541  				rw.Header().Set("Access-Control-Allow-Headers", "*")
  2542  			}
  2543  			return h(ctx, rw, req)
  2544  		}
  2545  
  2546  		return h(ctx, rw, req)
  2547  	}
  2548  }
  2549  `
  2550  
  2551  	regexpOriginsHandler = `// handleBottlesOrigin applies the CORS response headers corresponding to the origin.
  2552  func handleBottlesOrigin(h goa.Handler) goa.Handler {
  2553  	spec0 := regexp.MustCompile("[here|there].example.com")
  2554  
  2555  	return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
  2556  		origin := req.Header.Get("Origin")
  2557  		if origin == "" {
  2558  			// Not a CORS request
  2559  			return h(ctx, rw, req)
  2560  		}
  2561  		if cors.MatchOriginRegexp(origin, spec0) {
  2562  			ctx = goa.WithLogContext(ctx, "origin", origin)
  2563  			rw.Header().Set("Access-Control-Allow-Origin", origin)
  2564  			rw.Header().Set("Vary", "Origin")
  2565  			rw.Header().Set("Access-Control-Expose-Headers", "X-Three")
  2566  			rw.Header().Set("Access-Control-Allow-Credentials", "true")
  2567  			if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" {
  2568  				// We are handling a preflight request
  2569  				rw.Header().Set("Access-Control-Allow-Methods", "GET, POST")
  2570  				rw.Header().Set("Access-Control-Allow-Headers", "X-One, X-Two")
  2571  			}
  2572  			return h(ctx, rw, req)
  2573  		}
  2574  		if cors.MatchOrigin(origin, "there.example.com") {
  2575  			ctx = goa.WithLogContext(ctx, "origin", origin)
  2576  			rw.Header().Set("Access-Control-Allow-Origin", origin)
  2577  			rw.Header().Set("Vary", "Origin")
  2578  			rw.Header().Set("Access-Control-Allow-Credentials", "false")
  2579  			if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" {
  2580  				// We are handling a preflight request
  2581  				rw.Header().Set("Access-Control-Allow-Methods", "*")
  2582  				rw.Header().Set("Access-Control-Allow-Headers", "*")
  2583  			}
  2584  			return h(ctx, rw, req)
  2585  		}
  2586  
  2587  		return h(ctx, rw, req)
  2588  	}
  2589  }
  2590  `
  2591  
  2592  	encoderController = `
  2593  // MountBottlesController "mounts" a Bottles resource controller on the given service.
  2594  func MountBottlesController(service *goa.Service, ctrl BottlesController) {
  2595  	initService(service)
  2596  	var h goa.Handler
  2597  
  2598  	h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
  2599  		// Check if there was an error loading the request
  2600  		if err := goa.ContextError(ctx); err != nil {
  2601  			return err
  2602  		}
  2603  		// Build the context
  2604  		rctx, err := NewListBottleContext(ctx, req, service)
  2605  		if err != nil {
  2606  			return err
  2607  		}
  2608  		return ctrl.List(rctx)
  2609  	}
  2610  	service.Mux.Handle("GET", "/accounts/:accountID/bottles", ctrl.MuxHandler("list", h, nil))
  2611  	service.LogInfo("mount", "ctrl", "Bottles", "action", "List", "route", "GET /accounts/:accountID/bottles")
  2612  }
  2613  `
  2614  
  2615  	simpleMount = `func MountBottlesController(service *goa.Service, ctrl BottlesController) {
  2616  	initService(service)
  2617  	var h goa.Handler
  2618  
  2619  	h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
  2620  		// Check if there was an error loading the request
  2621  		if err := goa.ContextError(ctx); err != nil {
  2622  			return err
  2623  		}
  2624  		// Build the context
  2625  		rctx, err := NewListBottleContext(ctx, req, service)
  2626  		if err != nil {
  2627  			return err
  2628  		}
  2629  		return ctrl.List(rctx)
  2630  	}
  2631  	service.Mux.Handle("GET", "/accounts/:accountID/bottles", ctrl.MuxHandler("list", h, nil))
  2632  	service.LogInfo("mount", "ctrl", "Bottles", "action", "List", "route", "GET /accounts/:accountID/bottles")
  2633  }
  2634  `
  2635  
  2636  	multiController = `// BottlesController is the controller interface for the Bottles actions.
  2637  type BottlesController interface {
  2638  	goa.Muxer
  2639  	List(*ListBottleContext) error
  2640  	Show(*ShowBottleContext) error
  2641  }
  2642  `
  2643  
  2644  	multiMount = `func MountBottlesController(service *goa.Service, ctrl BottlesController) {
  2645  	initService(service)
  2646  	var h goa.Handler
  2647  
  2648  	h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
  2649  		// Check if there was an error loading the request
  2650  		if err := goa.ContextError(ctx); err != nil {
  2651  			return err
  2652  		}
  2653  		// Build the context
  2654  		rctx, err := NewListBottleContext(ctx, req, service)
  2655  		if err != nil {
  2656  			return err
  2657  		}
  2658  		return ctrl.List(rctx)
  2659  	}
  2660  	service.Mux.Handle("GET", "/accounts/:accountID/bottles", ctrl.MuxHandler("list", h, nil))
  2661  	service.LogInfo("mount", "ctrl", "Bottles", "action", "List", "route", "GET /accounts/:accountID/bottles")
  2662  
  2663  	h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
  2664  		// Check if there was an error loading the request
  2665  		if err := goa.ContextError(ctx); err != nil {
  2666  			return err
  2667  		}
  2668  		// Build the context
  2669  		rctx, err := NewShowBottleContext(ctx, req, service)
  2670  		if err != nil {
  2671  			return err
  2672  		}
  2673  		return ctrl.Show(rctx)
  2674  	}
  2675  	service.Mux.Handle("GET", "/accounts/:accountID/bottles/:id", ctrl.MuxHandler("show", h, nil))
  2676  	service.LogInfo("mount", "ctrl", "Bottles", "action", "Show", "route", "GET /accounts/:accountID/bottles/:id")
  2677  }
  2678  `
  2679  
  2680  	simpleResourceHref = `func BottleHref(id interface{}) string {
  2681  	paramid := strings.TrimLeftFunc(fmt.Sprintf("%v", id), func(r rune) bool { return r == '/' })
  2682  	return fmt.Sprintf("/bottles/%v", paramid)
  2683  }
  2684  `
  2685  	noParamHref = `func BottleHref() string {
  2686  	return "/bottles"
  2687  }
  2688  `
  2689  
  2690  	simpleUserType = `// simplePayload user type.
  2691  type simplePayload struct {
  2692  	Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty" xml:"name,omitempty"` + "`" + `
  2693  }
  2694  
  2695  
  2696  
  2697  // Publicize creates SimplePayload from simplePayload
  2698  func (ut *simplePayload) Publicize() *SimplePayload {
  2699  	var pub SimplePayload
  2700  		if ut.Name != nil {
  2701  		pub.Name = ut.Name
  2702  	}
  2703  	return &pub
  2704  }
  2705  
  2706  // SimplePayload user type.
  2707  type SimplePayload struct {
  2708  	Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty" xml:"name,omitempty"` + "`" + `
  2709  }
  2710  `
  2711  
  2712  	userTypeIncludingHash = `// complexPayload user type.
  2713  type complexPayload struct {
  2714  	Misc map[int]*miscPayload ` + "`" + `form:"misc,omitempty" json:"misc,omitempty" yaml:"misc,omitempty" xml:"misc,omitempty"` + "`" + `
  2715  	Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty" xml:"name,omitempty"` + "`" + `
  2716  }
  2717  
  2718  
  2719  
  2720  // Publicize creates ComplexPayload from complexPayload
  2721  func (ut *complexPayload) Publicize() *ComplexPayload {
  2722  	var pub ComplexPayload
  2723  		if ut.Misc != nil {
  2724  		pub.Misc = make(map[int]*MiscPayload, len(ut.Misc))
  2725  		for k2, v2 := range ut.Misc {
  2726  						pubk2 := k2
  2727  			var pubv2 *MiscPayload
  2728  			if v2 != nil {
  2729  						pubv2 = v2.Publicize()
  2730  			}
  2731  			pub.Misc[pubk2] = pubv2
  2732  		}
  2733  	}
  2734  	if ut.Name != nil {
  2735  		pub.Name = ut.Name
  2736  	}
  2737  	return &pub
  2738  }
  2739  
  2740  // ComplexPayload user type.
  2741  type ComplexPayload struct {
  2742  	Misc map[int]*MiscPayload ` + "`" + `form:"misc,omitempty" json:"misc,omitempty" yaml:"misc,omitempty" xml:"misc,omitempty"` + "`" + `
  2743  	Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty" xml:"name,omitempty"` + "`" + `
  2744  }
  2745  `
  2746  )