예제 #1
0
func WritePhp(data *Data) {
	MakeLibraryDir("php")
	RunTemplate := ChooseTemplate("php")

	RunTemplate("gitignore", ".gitignore", data)
	RunTemplate("composer.json", "composer.json", data)
	RunTemplate("readme.md", "README.md", data)

	MakeDir("lib")

	MakeDir(inflect.Camelize(data.Pkg.Name))
	RunTemplate("lib/Client.php", "Client.php", data)

	MakeDir("Exception")
	RunTemplate("lib/Exception/ExceptionInterface.php", "ExceptionInterface.php", data)
	RunTemplate("lib/Exception/ClientException.php", "ClientException.php", data)
	MoveDir("..")

	MakeDir("HttpClient")
	RunTemplate("lib/HttpClient/HttpClient.php", "HttpClient.php", data)
	RunTemplate("lib/HttpClient/AuthHandler.php", "AuthHandler.php", data)
	RunTemplate("lib/HttpClient/ErrorHandler.php", "ErrorHandler.php", data)
	RunTemplate("lib/HttpClient/RequestHandler.php", "RequestHandler.php", data)
	RunTemplate("lib/HttpClient/Response.php", "Response.php", data)
	RunTemplate("lib/HttpClient/ResponseHandler.php", "ResponseHandler.php", data)
	MoveDir("..")

	MakeDir("Api")

	for k, v := range data.Api["class"].(map[string]interface{}) {
		data.Api["active"] = ActiveClassInfo(k, v)
		RunTemplate("lib/Api/Api.php", inflect.Camelize(k)+".php", data)
		delete(data.Api, "active")
	}
}
예제 #2
0
파일: langs_php.go 프로젝트: devekko/alpaca
func WritePhp(data *Data) {
	MakeLibraryDir("php")
	RunTemplate := ChooseTemplate("php")

	RunTemplate("gitignore", ".gitignore", data)
	RunTemplate("composer.json", "composer.json", data)
	RunTemplate("readme.md", "README.md", data)

	MakeDir("lib")

	MakeDir(inflect.Camelize(data.Pkg.Name))
	RunTemplate("lib/Client.php", "Client.php", data)

	MakeDir("Exception")
	RunTemplate("lib/Exception/ExceptionInterface.php", "ExceptionInterface.php", data)
	RunTemplate("lib/Exception/ClientException.php", "ClientException.php", data)
	MoveDir("..")

	MakeDir("HttpClient")
	RunTemplate("lib/HttpClient/HttpClient.php", "HttpClient.php", data)
	RunTemplate("lib/HttpClient/AuthHandler.php", "AuthHandler.php", data)
	RunTemplate("lib/HttpClient/ErrorHandler.php", "ErrorHandler.php", data)
	RunTemplate("lib/HttpClient/RequestHandler.php", "RequestHandler.php", data)
	RunTemplate("lib/HttpClient/Response.php", "Response.php", data)
	RunTemplate("lib/HttpClient/ResponseHandler.php", "ResponseHandler.php", data)
	MoveDir("..")

	MakeDir("Api")

	for _, v := range data.Api.Classes {
		data.Active = &v
		RunTemplate("lib/Api/Api.php", inflect.Camelize(v.Name)+".php", data)
		data.Active = nil
	}
}
예제 #3
0
파일: api_analyzer.go 프로젝트: lopaka/rsc
func parseReturn(kind, resName, contentType string) string {
	switch kind {
	case "show":
		return refType(resName)
	case "index":
		return fmt.Sprintf("[]%s", refType(resName))
	case "create":
		if _, ok := noMediaTypeResources[resName]; ok {
			return "map[string]interface{}"
		}
		return "*" + inflect.Singularize(resName) + "Locator"
	case "update", "destroy":
		return ""
	case "current_instances":
		return "[]*Instance"
	default:
		switch {
		case len(contentType) == 0:
			return ""
		case strings.Index(contentType, "application/vnd.rightscale.") == 0:
			if contentType == "application/vnd.rightscale.text" {
				return "string"
			}
			elems := strings.SplitN(contentType[27:], ";", 2)
			name := refType(inflect.Camelize(elems[0]))
			if len(elems) > 1 && elems[1] == "type=collection" {
				name = "[]" + refType(inflect.Camelize(elems[0]))
			}
			return name
		default: // Shouldn't be here
			panic("api15gen: Unknown content type " + contentType)
		}
	}

}
//NewBuilder creates a build instance using the JSON schema data from the given filename. If modelName and/or pkgName
//are left empty the title-attribute of the JSON schema is used for:
// => struct-name (singular, camelcase e.g contact => Contact)
// => package name (pluralize, lowercased e.g. payment_reminder => paymentreminders)
func NewBuilder(inputFile string, modelName string, pkgName string) (builder Builder) {
	builder = Builder{}
	// try to read input file
	raw, err := ioutil.ReadFile(inputFile)
	if err != nil {
		msg := fmt.Sprintf("File error: %s", err)
		builder.Errors = append(builder.Errors, msg)
		return
	}
	builder.InputFile = inputFile
	builder.SchemaRaw = raw
	// try parsing json
	if err := json.Unmarshal(builder.SchemaRaw, &builder.SchemaJSON); err != nil {
		msg := fmt.Sprintf("JSON error: %s", err)
		builder.Errors = append(builder.Errors, msg)
		return
	}

	// defer model name from schema.title if not given as argument, schema['title'] MUST be set
	if len(modelName) > 0 {
		builder.ModelName = modelName
	} else {
		builder.ModelName = inflect.Typeify(builder.SchemaJSON["title"].(string))
	}
	// defer package name from schema.title if not given as argument
	if len(pkgName) > 0 {
		builder.PkgName = pkgName
	} else {
		//Pluralize no underscores
		builder.PkgName = strings.ToLower(inflect.Camelize(inflect.Pluralize(builder.SchemaJSON["title"].(string))))
	}

	return
}
예제 #5
0
파일: action.go 프로젝트: jianjunliu/goa
// Payload implements the action payload DSL. An action payload describes the HTTP request body
// data structure. The function accepts either a type or a DSL that describes the payload members
// using the Member DSL which accepts the same syntax as the Attribute DSL. This function can be
// called passing in a type, a DSL or both. Examples:
//
//	Payload(BottlePayload)		// Request payload is described by the BottlePayload type
//
//	Payload(func() {		// Request payload is an object and is described inline
//		Member("Name")
//	})
//
//	Payload(BottlePayload, func() {	// Request payload is described by merging the inline
//		Required("Name")	// definition into the BottlePayload type.
//	})
//
func Payload(p interface{}, dsls ...func()) {
	if len(dsls) > 1 {
		ReportError("too many arguments given to Payload")
		return
	}
	if a, ok := actionDefinition(true); ok {
		var att *design.AttributeDefinition
		var dsl func()
		switch actual := p.(type) {
		case func():
			dsl = actual
			att = newAttribute(a.Parent.MediaType)
			att.Type = design.Object{}
		case *design.AttributeDefinition:
			att = actual.Dup()
		case design.DataStructure:
			att = actual.Definition().Dup()
		case string:
			ut, ok := design.Design.Types[actual]
			if !ok {
				ReportError("unknown payload type %s", actual)
			}
			att = ut.AttributeDefinition.Dup()
		case *design.Array:
			att = &design.AttributeDefinition{Type: actual}
		case *design.Hash:
			att = &design.AttributeDefinition{Type: actual}
		case design.Primitive:
			att = &design.AttributeDefinition{Type: actual}
		}
		if len(dsls) == 1 {
			if dsl != nil {
				ReportError("invalid arguments in Payload call, must be (type), (dsl) or (type, dsl)")
			}
			dsl = dsls[0]
		}
		if dsl != nil {
			ExecuteDSL(dsl, att)
		}
		rn := inflect.Camelize(a.Parent.Name)
		an := inflect.Camelize(a.Name)
		a.Payload = &design.UserTypeDefinition{
			AttributeDefinition: att,
			TypeName:            fmt.Sprintf("%s%sPayload", an, rn),
		}
	}
}
예제 #6
0
//NewProperty creates a Property from a json string
func NewProperty(name string, values map[string]interface{}) Property {

	prop := Property{
		Name:      name,
		RawValues: values,
		FieldName: inflect.Camelize(name),
	}
	prop.setType()
	return prop
}
예제 #7
0
// Create API descriptor from raw resources and types
func (a *ApiAnalyzer) AnalyzeResource(name string, res map[string]interface{}, desc *gen.ApiDescriptor) error {
	name = inflect.Singularize(name)
	resource := gen.Resource{Name: name, ClientName: a.ClientName}

	// Description
	if d, ok := res["description"]; ok {
		resource.Description = removeBlankLines(d.(string))
	}

	// Attributes
	hasHref := false
	attributes := []*gen.Attribute{}
	m, ok := res["media_type"].(string)
	if ok {
		t, ok := a.RawTypes[m]
		if ok {
			attrs, ok := t["attributes"].(map[string]interface{})
			if ok {
				attributes = make([]*gen.Attribute, len(attrs))
				for idx, n := range sortedKeys(attrs) {
					if n == "href" {
						hasHref = true
					}
					param, err := a.AnalyzeAttribute(n, n, attrs[n].(map[string]interface{}))
					if err != nil {
						return err
					}
					attributes[idx] = &gen.Attribute{n, inflect.Camelize(n), param.Signature()}
				}
			}
		}
	}
	resource.Attributes = attributes
	if hasHref {
		resource.LocatorFunc = locatorFunc(name)
	}

	// Actions
	actions, err := a.AnalyzeActions(name, res)
	if err != nil {
		return err
	}
	resource.Actions = actions

	// Name and done
	resName := toGoTypeName(name, false)
	desc.Resources[resName] = &resource
	desc.ResourceNames = append(desc.ResourceNames, resName)

	return nil
}
예제 #8
0
// Helper method that creates or retrieve a object data type given its attributes.
func (a *ApiAnalyzer) CreateType(query string, attributes map[string]interface{}) (*gen.ObjectDataType, error) {
	name := inflect.Camelize(bracketRegexp.ReplaceAllLiteralString(query, "_") + "_struct")
	obj := a.Registry.CreateInlineType(name)
	obj.Fields = make([]*gen.ActionParam, len(attributes))
	for idx, an := range sortedKeys(attributes) {
		at := attributes[an]
		var childQ string
		if query == "payload" {
			childQ = an
		} else {
			childQ = fmt.Sprintf("%s[%s]", query, an)
		}
		att, err := a.AnalyzeAttribute(an, childQ, at.(map[string]interface{}))
		if err != nil {
			return nil, fmt.Errorf("Failed to compute type of attribute %s: %s", an, err)
		}
		obj.Fields[idx] = att
	}
	return obj, nil
}
예제 #9
0
파일: media_type.go 프로젝트: harboe/goa
// MediaType implements the media type definition DSL. A media type definition describes the
// representation of a resource used in a response body. This includes listing all the *potential*
// resource attributes that can appear in the body. Views specify which of the attributes are
// actually rendered so that the same media type definition may represent multiple rendering of a
// given resource representation.
//
// All media types must define a view named "default". This view is used to render the media type in
// response bodies when no other view is specified.
//
// A media type definition may also define links to other media types. This is done by first
// defining an attribute for the linked-to media type and then referring to that attribute in the
// Links DSL. Views may then elect to render one or the other or both. Links are rendered using the
// special "link" view. Media types that are linked to must define that view. Here is an example
// showing all the possible media type sub-definitions:
//
// 	MediaType("application/vnd.goa.example.bottle", func() {
//		Description("A bottle of wine")
//		Attributes(func() {
//			Attribute("id", Integer, "ID of bottle")
//			Attribute("href", String, "API href of bottle")
//			Attribute("account", Account, "Owner account")
//			Attribute("origin", Origin, "Details on wine origin")
//			Links(func() {
//				Link("account")        // Defines a link to the Account media type
//				Link("origin", "tiny") // Overrides the default view used to render links
//			})
//              	Required("id", "href")
//     		 })
//		View("default", func() {
//			Attribute("id")
//			Attribute("href")
//			Attribute("links") // Default view renders links
//		})
//		View("extended", func() {
//			Attribute("id")
//			Attribute("href")
//			Attribute("account") // Extended view renders account inline
//			Attribute("origin")  // Extended view renders origin inline
//			Attribute("links")   // Extended view also renders links
//		})
// 	})
//
// This function returns the media type definition so it can be referred to throughout the DSL.
func MediaType(identifier string, dsl func()) *design.MediaTypeDefinition {
	if design.Design == nil {
		InitDesign()
	}
	if design.Design.MediaTypes == nil {
		design.Design.MediaTypes = make(map[string]*design.MediaTypeDefinition)
	}
	if topLevelDefinition(true) {
		identifier, params, err := mime.ParseMediaType(identifier)
		if err != nil {
			ReportError("invalid media type identifier %#v: %s",
				identifier, err)
		}
		slash := strings.Index(identifier, "/")
		if slash == -1 {
			identifier += "/json"
		}
		identifier = mime.FormatMediaType(identifier, params)
		elems := strings.Split(identifier, ".")
		elems = strings.Split(elems[len(elems)-1], "/")
		elems = strings.Split(elems[0], "+")
		typeName := inflect.Camelize(elems[0])
		if typeName == "" {
			mediaTypeCount++
			typeName = fmt.Sprintf("MediaType%d", mediaTypeCount)
		}
		if _, ok := design.Design.MediaTypes[identifier]; ok {
			ReportError("media type %#v is defined twice", identifier)
			return nil
		}
		mt := design.NewMediaTypeDefinition(typeName, identifier, dsl)
		design.Design.MediaTypes[identifier] = mt
		return mt
	}
	return nil
}
예제 #10
0
// AnalyzeActions parses out a resource actions.
// Resource actions in the JSON consist of an array of map. The map keys are:
// "description", "name", "metadata", "urls", "headers", "params", "payload" and "responses".
func (a *APIAnalyzer) AnalyzeActions(resourceName string, resource map[string]interface{}) ([]*gen.Action, error) {
	methods := resource["actions"].([]interface{})
	actions := make([]*gen.Action, len(methods))
	for i, m := range methods {
		meth := m.(map[string]interface{})
		actionName := meth["name"].(string)
		description := fmt.Sprintf("No description provided for %s.", actionName)
		if d, _ := meth["description"]; d != nil {
			description = d.(string)
		}
		pathPatterns, err := a.ParseUrls(meth["urls"])
		if err != nil {
			return nil, err
		}
		params := []*gen.ActionParam{} // Query, path and payload params
		pathParamNames := []string{}
		queryParamNames := []string{}
		payloadParamNames := []string{}

		// Query and path params analysis
		if p, ok := meth["params"]; ok {
			param := p.(map[string]interface{})
			t, ok := param["type"]
			if !ok {
				return nil, fmt.Errorf("Missing type declaration in %s", prettify(p))
			}
			attrs := t.(map[string]interface{})["attributes"].(map[string]interface{})
			attrNames := sortedKeys(attrs)
			for _, pn := range attrNames {
				pt := attrs[pn]
				att, err := a.AnalyzeAttribute(pn, pn, pt.(map[string]interface{}))
				if err != nil {
					return nil, fmt.Errorf("Failed to compute type of param %s: %s", pn, err.Error())
				}
				isPathParam := false
				for _, pat := range pathPatterns {
					for _, v := range pat.Variables {
						if v == pn {
							isPathParam = true
							break
						}
					}
					if isPathParam {
						break
					}
				}
				if isPathParam {
					pathParamNames = append(pathParamNames, pn)
					att.Location = gen.PathParam
				} else {
					queryParamNames = append(queryParamNames, pn)
					att.Location = gen.QueryParam
					params = append(params, att)
				}
			}
		}

		// Initialize leaf params, all path and query params are leaf params
		leafParams := make([]*gen.ActionParam, len(queryParamNames))
		idx := 0
		for _, p := range params {
			if p.Location == gen.QueryParam {
				leafParams[idx] = p
				idx++
			}
		}
		paramNames := make([]string, len(queryParamNames))
		for i, n := range queryParamNames {
			paramNames[i] = n
		}

		// Payload params analysis
		var payload gen.DataType
		if p, ok := meth["payload"]; ok {
			as, ok := p.(map[string]interface{})["type"]
			if ok {
				pd, err := a.AnalyzeType(as.(map[string]interface{}), "payload")
				if err != nil {
					return nil, err
				}
				if po, ok := pd.(*gen.ObjectDataType); ok {

					// Remove the type since we are "flattening" the attributes
					// as top level params.
					// This is a bit hacky and should be refactored
					// (it should be possible to get the type without having
					// it be registered). Works for now(TM).
					delete(a.Registry.InlineTypes, po.TypeName)

					for _, att := range po.Fields {
						payloadParamNames = append(payloadParamNames, att.Name)
						att.Location = gen.PayloadParam
						params = append(params, att)
						extracted := extractLeafParams(att, att.Name, make(map[string]*[]*gen.ActionParam))
						for _, e := range extracted {
							e.Location = gen.PayloadParam
						}
						leafParams = append(leafParams, extracted...)
					}
				} else {
					// Raw payload (no attributes)
					payload = pd
					param := rawPayload(pd, p)
					params = append(params, param)
					leafParams = append(leafParams, param)
				}
			}
		}

		// Heuristic to check whether response returns a location header
		// Also extract response type from success response media type
		// TBD: support actions returning multiple success responses with media types?
		hasLocation := false
		var returnTypeName string
		responses, ok := meth["responses"]
		if ok {
			resps := responses.(map[string]interface{})
			respNames := sortedKeys(resps)
			for _, rName := range respNames {
				r := resps[rName]
				resp := r.(map[string]interface{})
				status := resp["status"]
				s := int(status.(float64))
				if s < 200 || s > 299 {
					continue // Skip error responses
				}
				if s == 201 && actionName == "create" {
					hasLocation = true
				} else if headers, ok := resp["headers"]; ok {
					if hname, ok := headers.(string); ok {
						// TBD is there a better way?
						hasLocation = hname == "Location" && actionName == "create"
					} else {
						head := headers.(map[string]interface{})
						keys, ok := head["keys"]
						if ok {
							headerKeys := keys.(map[string]interface{})
							for _, k := range headerKeys {
								// TBD is there a better way?
								if k == "Location" && actionName == "create" {
									hasLocation = true
								}
								break
							}
						}
					}
				}
				if returnTypeName == "" {
					if media, ok := resp["media_type"]; ok {
						m := media.(map[string]interface{})
						if name, ok := m["name"]; ok {
							returnTypeName = toGoTypeName(name.(string), true)
							a.descriptor.NeedJSON = true
							// Analyze return type to make sure it gets recorded
							_, err := a.AnalyzeType(a.RawTypes[name.(string)], "return")
							if err != nil {
								return nil, err
							}
						} else {
							// Default to string
							returnTypeName = "string"
						}
					} else if mime, ok := resp["mime_type"]; ok {
						// Resticle compat
						for n, r := range a.RawResources {
							if mt, ok := r["mime_type"]; ok {
								if mt == mime {
									if actionName == "index" {
										returnTypeName = "[]*" + n
									} else {
										returnTypeName = "*" + n
									}
									a.descriptor.NeedJSON = true
									break
								}
							}
						}
					}
				}
			}
		}
		if hasLocation {
			returnTypeName = fmt.Sprintf("*%sLocator", resourceName)
		}

		// Record action
		action := gen.Action{
			Name:              actionName,
			MethodName:        inflect.Camelize(actionName),
			Description:       removeBlankLines(description),
			ResourceName:      resourceName,
			PathPatterns:      pathPatterns,
			Payload:           payload,
			Params:            params,
			LeafParams:        leafParams,
			Return:            returnTypeName,
			ReturnLocation:    hasLocation,
			QueryParamNames:   queryParamNames,
			PayloadParamNames: payloadParamNames,
			PathParamNames:    pathParamNames,
		}
		actions[i] = &action
	}
	return actions, nil
}
예제 #11
0
파일: api_analyzer.go 프로젝트: lopaka/rsc
// AnalyzeResource analyzes the given resource and updates the Resources and ParamTypes analyzer
// fields accordingly
func (a *APIAnalyzer) AnalyzeResource(name string, resource interface{}, descriptor *gen.APIDescriptor) {
	var res = resource.(map[string]interface{})

	// Compute description
	var description string
	if d, ok := res["description"].(string); ok {
		description = d
	}

	// Compute attributes
	var attributes []*gen.Attribute
	var atts map[string]interface{}
	if m, ok := res["media_type"].(map[string]interface{}); ok {
		atts = m["attributes"].(map[string]interface{})
		attributes = make([]*gen.Attribute, len(atts))
		for idx, n := range sortedKeys(atts) {
			at, ok := a.attributeTypes[n+"#"+name]
			if !ok {
				at = a.attributeTypes[n]
			}
			attributes[idx] = &gen.Attribute{n, inflect.Camelize(n), at}
		}
	} else {
		attributes = []*gen.Attribute{}
	}

	// Compute actions
	var methods = res["methods"].(map[string]interface{})
	var actionNames = sortedKeys(methods)
	var actions = []*gen.Action{}
	for _, actionName := range actionNames {
		var m = methods[actionName]
		var meth = m.(map[string]interface{})
		var params map[string]interface{}
		if p, ok := meth["parameters"]; ok {
			params = p.(map[string]interface{})
		}
		var description = "No description provided for " + actionName + "."
		if d, _ := meth["description"]; d != nil {
			description = d.(string)
		}
		var pathPatterns = ParseRoute(fmt.Sprintf("%s#%s", name, actionName),
			meth["route"].(string))
		if len(pathPatterns) == 0 {
			// Custom action
			continue
		}
		var allParamNames = make([]string, len(params))
		var i = 0
		for n := range params {
			allParamNames[i] = n
			i++
		}
		sort.Strings(allParamNames)

		var contentType string
		if c, ok := meth["content_type"].(string); ok {
			contentType = c
		}
		var paramAnalyzer = NewAnalyzer(params)
		paramAnalyzer.Analyze()

		// Record new parameter types
		var paramTypeNames = make([]string, len(paramAnalyzer.ParamTypes))
		var idx = 0
		for n := range paramAnalyzer.ParamTypes {
			paramTypeNames[idx] = n
			idx++
		}
		sort.Strings(paramTypeNames)
		for _, name := range paramTypeNames {
			var pType = paramAnalyzer.ParamTypes[name]
			if _, ok := a.rawTypes[name]; ok {
				a.rawTypes[name] = append(a.rawTypes[name], pType)
			} else {
				a.rawTypes[name] = []*gen.ObjectDataType{pType}
			}
		}

		// Update description with parameter descriptions
		var mandatory []string
		var optional []string
		for _, p := range paramAnalyzer.Params {
			if p.Mandatory {
				desc := p.Name
				if p.Description != "" {
					desc += ": " + strings.TrimSpace(p.Description)
				}
				mandatory = append(mandatory, desc)
			} else {
				desc := p.Name
				if p.Description != "" {
					desc += ": " + strings.TrimSpace(p.Description)
				}
				optional = append(optional, desc)
			}
		}
		if len(mandatory) > 0 {
			sort.Strings(mandatory)
			if !strings.HasSuffix(description, "\n") {
				description += "\n"
			}
			description += "Required parameters:\n\t" + strings.Join(mandatory, "\n\t")
		}
		if len(optional) > 0 {
			sort.Strings(optional)
			if !strings.HasSuffix(description, "\n") {
				description += "\n"
			}
			description += "Optional parameters:\n\t" + strings.Join(optional, "\n\t")
		}

		// Sort parameters by location
		actionParams := paramAnalyzer.Params
		leafParams := paramAnalyzer.LeafParams
		var pathParamNames []string
		var queryParamNames []string
		var payloadParamNames []string
		for _, p := range leafParams {
			n := p.Name
			if isQueryParam(n) {
				queryParamNames = append(queryParamNames, n)
				p.Location = gen.QueryParam
			} else if isPathParam(n, pathPatterns) {
				pathParamNames = append(pathParamNames, n)
				p.Location = gen.PathParam
			} else {
				payloadParamNames = append(payloadParamNames, n)
				p.Location = gen.PayloadParam
			}
		}
		for _, p := range actionParams {
			done := false
			for _, ap := range leafParams {
				if ap == p {
					done = true
					break
				}
			}
			if done {
				continue
			}
			n := p.Name
			if isQueryParam(n) {
				p.Location = gen.QueryParam
			} else if isPathParam(n, pathPatterns) {
				p.Location = gen.PathParam
			} else {
				p.Location = gen.PayloadParam
			}
		}

		// Mix in filters information
		if filters, ok := meth["filters"]; ok {
			var filterParam *gen.ActionParam
			for _, p := range actionParams {
				if p.Name == "filter" {
					filterParam = p
					break
				}
			}
			if filterParam != nil {
				values := sortedKeys(filters.(map[string]interface{}))
				ivalues := make([]interface{}, len(values))
				for i, v := range values {
					ivalues[i] = v
				}
				filterParam.ValidValues = ivalues
			}
		}

		// Record action
		action := gen.Action{
			Name:              actionName,
			MethodName:        inflect.Camelize(actionName),
			Description:       removeBlankLines(description),
			ResourceName:      inflect.Singularize(name),
			PathPatterns:      pathPatterns,
			Params:            actionParams,
			LeafParams:        paramAnalyzer.LeafParams,
			Return:            parseReturn(actionName, name, contentType),
			ReturnLocation:    actionName == "create" && name != "Oauth2",
			PathParamNames:    pathParamNames,
			QueryParamNames:   queryParamNames,
			PayloadParamNames: payloadParamNames,
		}
		actions = append(actions, &action)
	}

	// We're done!
	name = inflect.Singularize(name)
	descriptor.Resources[name] = &gen.Resource{
		Name:        name,
		ClientName:  "API",
		Description: removeBlankLines(description),
		Actions:     actions,
		Attributes:  attributes,
		LocatorFunc: LocatorFunc(attributes, name),
	}
}
예제 #12
0
// upperCamelCase returns camel case version of a word
// with upper case first character
func upperCamelCase(s string) string {
	return inflect.Camelize(s)
}