// Execute writes the code for the context types to the writer. func (w *MediaTypesWriter) Execute(mt *design.MediaTypeDefinition) error { var mLinks *design.UserTypeDefinition viewMT := mt err := mt.IterateViews(func(view *design.ViewDefinition) error { p, links, err := mt.Project(view.Name) if mLinks == nil { mLinks = links } if err != nil { return err } viewMT = p if err := w.ExecuteTemplate("mediatype", mediaTypeT, nil, viewMT); err != nil { return err } return nil }) if err != nil { return err } if mLinks != nil { if err := w.ExecuteTemplate("mediatypelink", mediaTypeLinkT, nil, mLinks); err != nil { return err } } return nil }
// Execute writes the code for the context types to the writer. func (w *MediaTypesWriter) Execute(mt *design.MediaTypeDefinition) error { var ( mLinks *design.UserTypeDefinition fn = template.FuncMap{"validationCode": w.Validator.Code} ) err := mt.IterateViews(func(view *design.ViewDefinition) error { p, links, err := mt.Project(view.Name) if mLinks == nil { mLinks = links } if err != nil { return err } if err := w.ExecuteTemplate("mediatype", mediaTypeT, fn, p); err != nil { return err } return nil }) if err != nil { return err } if mLinks != nil { if err := w.ExecuteTemplate("mediatypelink", mediaTypeLinkT, fn, mLinks); err != nil { return err } } return nil }
// MediaTypeRef produces the JSON reference to the media type definition with the given view. func MediaTypeRef(api *design.APIDefinition, mt *design.MediaTypeDefinition, view string) string { projected, _, err := mt.Project(view) if err != nil { panic(fmt.Sprintf("failed to project media type %#v: %s", mt.Identifier, err)) // bug } if _, ok := Definitions[projected.TypeName]; !ok { GenerateMediaTypeDefinition(api, projected, "default") } ref := fmt.Sprintf("#/definitions/%s", projected.TypeName) return ref }
func (g *Generator) okResp(a *design.ActionDefinition) map[string]interface{} { var ok *design.ResponseDefinition for _, resp := range a.Responses { if resp.Status == 200 { ok = resp break } } if ok == nil { return nil } var mt *design.MediaTypeDefinition var ok2 bool if mt, ok2 = design.Design.MediaTypes[design.CanonicalIdentifier(ok.MediaType)]; !ok2 { return nil } view := ok.ViewName if view == "" { view = design.DefaultView } pmt, _, err := mt.Project(view) if err != nil { return nil } var typeref string if pmt.IsError() { typeref = `goa.ErrInternal("not implemented")` } else { name := codegen.GoTypeRef(pmt, pmt.AllRequired(), 1, false) var pointer string if strings.HasPrefix(name, "*") { name = name[1:] pointer = "*" } typeref = fmt.Sprintf("%s%s.%s", pointer, g.Target, name) if strings.HasPrefix(typeref, "*") { typeref = "&" + typeref[1:] } typeref += "{}" } var nameSuffix string if view != "default" { nameSuffix = codegen.Goify(view, true) } return map[string]interface{}{ "Name": ok.Name + nameSuffix, "GoType": codegen.GoNativeType(pmt), "TypeRef": typeref, } }
func okResp(a *design.ActionDefinition) map[string]interface{} { var ok *design.ResponseDefinition for _, resp := range a.Responses { if resp.Status == 200 { ok = resp break } } if ok == nil { return nil } var mt *design.MediaTypeDefinition var ok2 bool if mt, ok2 = design.Design.MediaTypes[design.CanonicalIdentifier(ok.MediaType)]; !ok2 { return nil } view := "default" if _, ok := mt.Views["default"]; !ok { for v := range mt.Views { view = v break } } pmt, _, err := mt.Project(view) if err != nil { return nil } name := codegen.GoTypeRef(pmt, pmt.AllRequired(), 1, false) var pointer string if strings.HasPrefix(name, "*") { name = name[1:] pointer = "*" } typeref := fmt.Sprintf("%s%s.%s", pointer, TargetPackage, name) if strings.HasPrefix(typeref, "*") { typeref = "&" + typeref[1:] } var nameSuffix string if view != "default" { nameSuffix = codegen.Goify(view, true) } return map[string]interface{}{ "Name": ok.Name + nameSuffix, "GoType": codegen.GoNativeType(pmt), "TypeRef": typeref, } }
// buildMediaTypeSchema initializes s as the JSON schema representing mt for the given view. func buildMediaTypeSchema(api *design.APIDefinition, mt *design.MediaTypeDefinition, view string, s *JSONSchema) { s.Media = &JSONMedia{Type: mt.Identifier} projected, linksUT, err := mt.Project(view) if err != nil { panic(fmt.Sprintf("failed to project media type %#v: %s", mt.Identifier, err)) // bug } if linksUT != nil { links := linksUT.Type.ToObject() lnames := make([]string, len(links)) i := 0 for n := range links { lnames[i] = n i++ } sort.Strings(lnames) for _, ln := range lnames { var ( att = links[ln] lmt = att.Type.(*design.MediaTypeDefinition) r = lmt.Resource href string ) if r != nil { href = toSchemaHref(api, r.CanonicalAction().Routes[0]) } sm := NewJSONSchema() sm.Ref = MediaTypeRef(api, lmt, "default") s.Links = append(s.Links, &JSONLink{ Title: ln, Rel: ln, Description: att.Description, Href: href, Method: "GET", TargetSchema: sm, MediaType: lmt.Identifier, }) } } buildAttributeSchema(api, s, projected.AttributeDefinition) }
// Execute writes the code for the context types to the writer. func (w *ContextsWriter) Execute(data *ContextTemplateData) error { if err := w.ExecuteTemplate("context", ctxT, nil, data); err != nil { return err } fn := template.FuncMap{ "newCoerceData": newCoerceData, "arrayAttribute": arrayAttribute, "canonicalHeaderKey": http.CanonicalHeaderKey, } if err := w.ExecuteTemplate("new", ctxNewT, fn, data); err != nil { return err } if data.Payload != nil { found := false for _, t := range design.Design.Types { if t.TypeName == data.Payload.TypeName { found = true break } } if !found { fn := template.FuncMap{ "finalizeCode": w.Finalizer.Code, "validationCode": w.Validator.Code, } if err := w.ExecuteTemplate("payload", payloadT, fn, data); err != nil { return err } } } return data.IterateResponses(func(resp *design.ResponseDefinition) error { respData := map[string]interface{}{ "Context": data, "Response": resp, } var mt *design.MediaTypeDefinition if resp.Type != nil { var ok bool if mt, ok = resp.Type.(*design.MediaTypeDefinition); !ok { respData["Type"] = resp.Type respData["ContentType"] = resp.MediaType return w.ExecuteTemplate("response", ctxTRespT, nil, respData) } } else { mt = design.Design.MediaTypeWithIdentifier(resp.MediaType) } if mt != nil { var views []string if resp.ViewName != "" { views = []string{resp.ViewName} } else { views = make([]string, len(mt.Views)) i := 0 for name := range mt.Views { views[i] = name i++ } sort.Strings(views) } for _, view := range views { projected, _, err := mt.Project(view) if err != nil { return err } respData["Projected"] = projected respData["ViewName"] = view respData["MediaType"] = mt respData["ContentType"] = mt.ContentType if view == "default" { respData["RespName"] = codegen.Goify(resp.Name, true) } else { base := fmt.Sprintf("%s%s", resp.Name, strings.Title(view)) respData["RespName"] = codegen.Goify(base, true) } if err := w.ExecuteTemplate("response", ctxMTRespT, fn, respData); err != nil { return err } } return nil } return w.ExecuteTemplate("response", ctxNoMTRespT, nil, respData) }) }
func createTestMethod(resource *design.ResourceDefinition, action *design.ActionDefinition, response *design.ResponseDefinition, route *design.RouteDefinition, routeIndex int, mediaType *design.MediaTypeDefinition, view *design.ViewDefinition) TestMethod { routeNameQualifier := suffixRoute(action.Routes, routeIndex) viewNameQualifier := func() string { if view != nil && view.Name != "default" { return view.Name } return "" }() method := TestMethod{} method.Name = fmt.Sprintf("%s%s%s%s%s", codegen.Goify(action.Name, true), codegen.Goify(resource.Name, true), codegen.Goify(response.Name, true), routeNameQualifier, codegen.Goify(viewNameQualifier, true)) method.ActionName = codegen.Goify(action.Name, true) method.ResourceName = codegen.Goify(resource.Name, true) method.Comment = fmt.Sprintf("test setup") method.ControllerName = fmt.Sprintf("%s.%sController", TargetPackage, codegen.Goify(resource.Name, true)) method.ContextVarName = fmt.Sprintf("%sCtx", codegen.Goify(action.Name, false)) method.ContextType = fmt.Sprintf("%s.New%s%sContext", TargetPackage, codegen.Goify(action.Name, true), codegen.Goify(resource.Name, true)) method.RouteVerb = route.Verb method.Status = response.Status method.FullPath = goPathFormat(route.FullPath()) if view != nil && mediaType != nil { p, _, err := mediaType.Project(view.Name) if err != nil { panic(err) } tmp := codegen.GoTypeName(p, nil, 0, false) if !p.IsBuiltIn() { tmp = fmt.Sprintf("%s.%s", TargetPackage, tmp) } validate := codegen.RecursiveChecker(p.AttributeDefinition, false, false, false, "payload", "raw", 1, true) returnType := ObjectType{} returnType.Type = tmp returnType.Pointer = "*" returnType.Validatable = validate != "" method.ReturnType = &returnType } if len(route.Params()) > 0 { var params = []ObjectType{} for _, paramName := range route.Params() { for name, att := range action.Params.Type.ToObject() { if name == paramName { param := ObjectType{} param.Name = codegen.Goify(name, false) param.Type = codegen.GoTypeRef(att.Type, nil, 0, false) if att.Type.IsPrimitive() && action.Params.IsPrimitivePointer(name) { param.Pointer = "*" } params = append(params, param) } } } method.Params = params } if action.Payload != nil { payload := ObjectType{} payload.Name = "payload" payload.Type = fmt.Sprintf("%s.%s", TargetPackage, codegen.Goify(action.Payload.TypeName, true)) if !action.Payload.IsPrimitive() && !action.Payload.IsArray() && !action.Payload.IsHash() { payload.Pointer = "*" } validate := codegen.RecursiveChecker(action.Payload.AttributeDefinition, false, false, false, "payload", "raw", 1, true) if validate != "" { payload.Validatable = true } method.Payload = &payload } return method }
func (g *Generator) createTestMethod(resource *design.ResourceDefinition, action *design.ActionDefinition, response *design.ResponseDefinition, route *design.RouteDefinition, routeIndex int, mediaType *design.MediaTypeDefinition, view *design.ViewDefinition) *TestMethod { var ( actionName, ctrlName, varName string routeQualifier, viewQualifier, respQualifier string comment string returnType *ObjectType payload *ObjectType ) actionName = codegen.Goify(action.Name, true) ctrlName = codegen.Goify(resource.Name, true) varName = codegen.Goify(action.Name, false) routeQualifier = suffixRoute(action.Routes, routeIndex) if view != nil && view.Name != "default" { viewQualifier = codegen.Goify(view.Name, true) } respQualifier = codegen.Goify(response.Name, true) hasReturnValue := view != nil && mediaType != nil if hasReturnValue { p, _, err := mediaType.Project(view.Name) if err != nil { panic(err) // bug } tmp := codegen.GoTypeName(p, nil, 0, false) if !p.IsError() { tmp = fmt.Sprintf("%s.%s", g.Target, tmp) } validate := g.validator.Code(p.AttributeDefinition, false, false, false, "payload", "raw", 1, false) returnType = &ObjectType{} returnType.Type = tmp if p.IsObject() && !p.IsError() { returnType.Pointer = "*" } returnType.Validatable = validate != "" } comment = "runs the method " + actionName + " of the given controller with the given parameters" if action.Payload != nil { comment += " and payload" } comment += ".\n// It returns the response writer so it's possible to inspect the response headers" if hasReturnValue { comment += " and the media type struct written to the response" } comment += "." if action.Payload != nil { payload = &ObjectType{} payload.Name = "payload" payload.Type = fmt.Sprintf("%s.%s", g.Target, codegen.Goify(action.Payload.TypeName, true)) if !action.Payload.IsPrimitive() && !action.Payload.IsArray() && !action.Payload.IsHash() { payload.Pointer = "*" } validate := g.validator.Code(action.Payload.AttributeDefinition, false, false, false, "payload", "raw", 1, false) if validate != "" { payload.Validatable = true } } return &TestMethod{ Name: fmt.Sprintf("%s%s%s%s%s", actionName, ctrlName, respQualifier, routeQualifier, viewQualifier), ActionName: actionName, ResourceName: ctrlName, Comment: comment, Params: pathParams(action, route), QueryParams: queryParams(action), Headers: headers(action), Payload: payload, ReturnType: returnType, ReturnsErrorMedia: mediaType == design.ErrorMedia, ControllerName: fmt.Sprintf("%s.%sController", g.Target, ctrlName), ContextVarName: fmt.Sprintf("%sCtx", varName), ContextType: fmt.Sprintf("%s.New%s%sContext", g.Target, actionName, ctrlName), RouteVerb: route.Verb, Status: response.Status, FullPath: goPathFormat(route.FullPath()), } }