// Generate the application code, implement codegen.Generator. func (g *Generator) Generate(api *design.APIDefinition) ([]string, error) { if api == nil { return nil, fmt.Errorf("missing API definition, make sure design.Design is properly initialized") } title := fmt.Sprintf("%s: Application Contexts", api.Name) imports := []*codegen.ImportSpec{ codegen.SimpleImport("github.com/raphael/goa"), codegen.SimpleImport("strconv"), } g.ContextsWriter.WriteHeader(title, TargetPackage, imports) err := api.IterateResources(func(r *design.ResourceDefinition) error { return r.IterateActions(func(a *design.ActionDefinition) error { ctxName := codegen.Goify(a.Name, true) + codegen.Goify(a.Parent.Name, true) + "Context" ctxData := ContextTemplateData{ Name: ctxName, ResourceName: r.Name, ActionName: a.Name, Payload: a.Payload, Params: a.AllParams(), Headers: r.Headers.Merge(a.Headers), Routes: a.Routes, Responses: MergeResponses(r.Responses, a.Responses), MediaTypes: api.MediaTypes, Types: api.Types, } return g.ContextsWriter.Execute(&ctxData) }) }) g.genfiles = append(g.genfiles, g.contextsFilename) if err != nil { g.Cleanup() return nil, err } if err := g.ContextsWriter.FormatCode(); err != nil { g.Cleanup() return nil, err } title = fmt.Sprintf("%s: Application Controllers", api.Name) imports = []*codegen.ImportSpec{ codegen.SimpleImport("github.com/julienschmidt/httprouter"), codegen.SimpleImport("github.com/raphael/goa"), } g.ControllersWriter.WriteHeader(title, TargetPackage, imports) var controllersData []*ControllerTemplateData api.IterateResources(func(r *design.ResourceDefinition) error { data := &ControllerTemplateData{Resource: codegen.Goify(r.Name, true)} err := r.IterateActions(func(a *design.ActionDefinition) error { context := fmt.Sprintf("%s%sContext", codegen.Goify(a.Name, true), codegen.Goify(r.Name, true)) action := map[string]interface{}{ "Name": codegen.Goify(a.Name, true), "Routes": a.Routes, "Context": context, } data.Actions = append(data.Actions, action) return nil }) if err != nil { return err } if len(data.Actions) > 0 { controllersData = append(controllersData, data) } return nil }) g.genfiles = append(g.genfiles, g.controllersFilename) if err := g.ControllersWriter.Execute(controllersData); err != nil { g.Cleanup() return nil, err } if err := g.ControllersWriter.FormatCode(); err != nil { g.Cleanup() return nil, err } title = fmt.Sprintf("%s: Application Resource Href Factories", api.Name) g.ResourcesWriter.WriteHeader(title, TargetPackage, nil) err = api.IterateResources(func(r *design.ResourceDefinition) error { m, ok := api.MediaTypes[r.MediaType] var identifier string if ok { identifier = m.Identifier } else { identifier = "application/text" } canoTemplate := r.URITemplate() canoTemplate = design.WildcardRegex.ReplaceAllLiteralString(canoTemplate, "/%v") var canoParams []string if ca := r.CanonicalAction(); ca != nil { if len(ca.Routes) > 0 { canoParams = ca.Routes[0].Params() } } data := ResourceData{ Name: codegen.Goify(r.Name, true), Identifier: identifier, Description: r.Description, Type: m, CanonicalTemplate: canoTemplate, CanonicalParams: canoParams, } return g.ResourcesWriter.Execute(&data) }) g.genfiles = append(g.genfiles, g.resourcesFilename) if err != nil { g.Cleanup() return nil, err } if err := g.ResourcesWriter.FormatCode(); err != nil { g.Cleanup() return nil, err } title = fmt.Sprintf("%s: Application Media Types", api.Name) imports = []*codegen.ImportSpec{ codegen.SimpleImport("github.com/raphael/goa"), codegen.SimpleImport("fmt"), } g.MediaTypesWriter.WriteHeader(title, TargetPackage, imports) err = api.IterateMediaTypes(func(mt *design.MediaTypeDefinition) error { if mt.Type.IsObject() || mt.Type.IsArray() { return g.MediaTypesWriter.Execute(mt) } return nil }) g.genfiles = append(g.genfiles, g.mediaTypesFilename) if err != nil { g.Cleanup() return nil, err } if err := g.MediaTypesWriter.FormatCode(); err != nil { g.Cleanup() return nil, err } title = fmt.Sprintf("%s: Application User Types", api.Name) g.UserTypesWriter.WriteHeader(title, TargetPackage, nil) err = api.IterateUserTypes(func(t *design.UserTypeDefinition) error { return g.UserTypesWriter.Execute(t) }) g.genfiles = append(g.genfiles, g.userTypesFilename) if err != nil { g.Cleanup() return nil, err } if err := g.UserTypesWriter.FormatCode(); err != nil { g.Cleanup() return nil, err } return g.genfiles, nil }