Beispiel #1
0
// 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
}
Beispiel #2
0
// 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
}
Beispiel #3
0
func typeName(mt *design.MediaTypeDefinition) string {
	name := codegen.GoTypeName(mt, mt.AllRequired(), 1, false)
	if mt.IsBuiltIn() {
		return strings.Split(name, ".")[1]
	}
	return name
}
Beispiel #4
0
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
	}
	name := codegen.GoTypeRef(mt, mt.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:]
	}
	return map[string]interface{}{
		"Name":    ok.Name,
		"GoType":  codegen.GoNativeType(mt),
		"TypeRef": typeref,
	}
}
Beispiel #5
0
// 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
}
Beispiel #6
0
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,
	}
}
Beispiel #7
0
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,
	}
}
Beispiel #8
0
// 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)
}
Beispiel #9
0
func fieldAssignmentModelToType(model *RelationalModelDefinition, ut *design.MediaTypeDefinition, mtype, utype string) string {
	//utPackage := "app"
	var fieldAssignments []string
	// type.Field = model.Field
	for fname, field := range model.RelationalFields {
		if field.Datatype == "" {
			continue
		}
		var mpointer, upointer bool
		mpointer = field.Nullable
		obj := ut.ToObject()
		definition := ut.Definition()
		for key := range obj {
			gfield := obj[key]
			if field.Underscore() == key || field.DatabaseFieldName == key {
				// this is our field
				if gfield.Type.IsObject() || definition.IsPrimitivePointer(key) {
					upointer = true
				} else {
					// set it explicity because we're reusing the same bool
					upointer = false
				}

				var prefix string
				if upointer && !mpointer {
					// ufield = &mfield
					prefix = "&"
				} else if mpointer && !upointer {
					// ufield = *mfield (rare if never?)
					prefix = "*"
				}

				fa := fmt.Sprintf("\t%s.%s = %s%s.%s", utype, codegen.Goify(key, true), prefix, mtype, fname)
				fieldAssignments = append(fieldAssignments, fa)
			}
		}
	}
	return strings.Join(fieldAssignments, "\n")
}
Beispiel #10
0
// 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)
	})
}
Beispiel #11
0
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
}
Beispiel #12
0
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()),
	}
}
Beispiel #13
0
func typeName(mt *design.MediaTypeDefinition) string {
	if mt.IsError() {
		return "ErrorResponse"
	}
	return codegen.GoTypeName(mt, mt.AllRequired(), 1, false)
}