func (api *API) generateAPICode(apiName string) string { className := strings.Title(apiName) packageName := strings.ToLower(apiName) content := `package org.mozilla.taskcluster.client.` + packageName + `; import org.mozilla.taskcluster.client.APICallFailure; import org.mozilla.taskcluster.client.CallSummary; import org.mozilla.taskcluster.client.Credentials; import org.mozilla.taskcluster.client.EmptyPayload; import org.mozilla.taskcluster.client.TaskClusterRequestHandler; ` comment := "/**\n" if api.Description != "" { comment += utils.Indent(api.Description, " * ", true) } if len(comment) >= 1 && comment[len(comment)-1:] != "\n" { comment += "\n" } comment += " *\n" comment += fmt.Sprintf(" * @see \"[%v API Documentation](%v)\"\n", className, api.apiDef.DocRoot) comment += " */\n" content += comment content += "public class " + className + ` extends TaskClusterRequestHandler { protected static final String defaultBaseURL = "` + api.BaseURL + `"; public ` + className + `(Credentials credentials) { super(credentials, defaultBaseURL); } public ` + className + `(Credentials credentials, String baseURL) { super(credentials, baseURL); } public ` + className + `(String clientId, String accessToken) { super(new Credentials(clientId, accessToken), defaultBaseURL); } public ` + className + `(String clientId, String accessToken, String certificate) { super(new Credentials(clientId, accessToken, certificate), defaultBaseURL); } public ` + className + `(String baseURL) { super(baseURL); } public ` + className + `() { super(defaultBaseURL); } ` for _, entry := range api.Entries { content += entry.generateAPICode(apiName) } content += "}" return content }
func (entry *APIEntry) generateAPICode(apiName string) string { comment := "\n /**\n" if entry.Description != "" { comment += utils.Indent(entry.Description, " * ", true) } if len(comment) >= 1 && comment[len(comment)-1:] != "\n" { comment += "\n" } comment += requiredScopesComment(entry.Scopes) comment += " *\n" comment += fmt.Sprintf(" * @see \"[%v API Documentation](%v#%v)\"\n", entry.Title, entry.Parent.apiDef.DocRoot, entry.Name) comment += " */\n" inputParams := "" if len(entry.Args) > 0 { inputParams += "String " + strings.Join(entry.Args, ", String ") } apiArgsPayload := "null" if entry.Input != "" { apiArgsPayload = "payload" p := entry.Parent.apiDef.schemas.SubSchema(entry.Input).TypeName + " payload" if inputParams == "" { inputParams = p } else { inputParams += ", " + p } } requestType := "EmptyPayload" if entry.Input != "" { requestType = entry.Parent.apiDef.schemas.SubSchema(entry.Input).TypeName } responseType := "EmptyPayload" if entry.Output != "" { responseType = entry.Parent.apiDef.schemas.SubSchema(entry.Output).TypeName } returnType := "CallSummary<" + requestType + ", " + responseType + ">" content := comment content += " public " + returnType + " " + entry.MethodName + "(" + inputParams + ") throws APICallFailure {\n" content += " return apiCall(" + apiArgsPayload + ", \"" + strings.ToUpper(entry.Method) + "\", \"" + strings.Replace(strings.Replace(entry.Route, "<", "\" + uriEncode(", -1), ">", ") + \"", -1) + "\", " + responseType + ".class);\n" content += " }\n" // can remove any code that added an empty string to another string return strings.Replace(content, ` + ""`, "", -1) }
func (jsonSubSchema *JsonSubSchema) TypeDefinition(level int, extraPackages map[string]bool) (classDefinition, comment, typ string) { if d := jsonSubSchema.Description; d != nil { if desc := *d; desc != "" { comment += desc } } if comment != "" && comment[len(comment)-1:] != "\n" { comment += "\n" } // Create comments for metadata in a single paragraph. Only start new // paragraph if we discover after inspecting all possible metadata, that // something has been specified. If there is no metadata, no need to create // a new paragraph. var metadata string if enum := jsonSubSchema.Enum; enum != nil { metadata += "Possible values:\n" for _, i := range enum { switch i.(type) { case float64: metadata += fmt.Sprintf(" * %v\n", i) default: metadata += fmt.Sprintf(" * %q\n", i) } } } if def := jsonSubSchema.Default; def != nil { var value string switch (*def).(type) { case bool: value = strconv.FormatBool((*def).(bool)) case float64: value = strconv.FormatFloat((*def).(float64), 'g', -1, 64) default: value = fmt.Sprintf("%q", *def) } metadata += "Default: " + value + "\n" } if regex := jsonSubSchema.Pattern; regex != nil { metadata += "Syntax: " + *regex + "\n" } if minItems := jsonSubSchema.MinLength; minItems != nil { metadata += "Min length: " + strconv.Itoa(*minItems) + "\n" } if maxItems := jsonSubSchema.MaxLength; maxItems != nil { metadata += "Max length: " + strconv.Itoa(*maxItems) + "\n" } if minimum := jsonSubSchema.Minimum; minimum != nil { metadata += "Mininum: " + strconv.Itoa(*minimum) + "\n" } if maximum := jsonSubSchema.Maximum; maximum != nil { metadata += "Maximum: " + strconv.Itoa(*maximum) + "\n" } // Here we check if metadata was specified, and only create new // paragraph (`*\n`) if something was. if len(metadata) > 0 { comment += "\n" + metadata } if URL := jsonSubSchema.SourceURL; URL != "" { u, err := url.Parse(URL) if err == nil && u.Scheme != "file" { if len(comment) > 1 { comment += "\n" } comment += "See " + URL + "\n" } } comment = utils.Comment(comment, "") typ = "Object" if p := jsonSubSchema.Type; p != nil { typ = *p } if p := jsonSubSchema.RefSubSchema; p != nil { j := JsonSubSchema(*jsonSubSchema.RefSubSchema) _, _, possSimpleType := (&j).TypeDefinition(0, make(map[string]bool)) switch possSimpleType { case "": typ = p.TypeName default: typ = possSimpleType } } switch typ { case "array": if jsonSubSchema.Items != nil { if jsonSubSchema.Items.Type != nil { j := JsonSubSchema(*jsonSubSchema.Items) subClassDefinition, _, subType := (&j).TypeDefinition(level, extraPackages) if subType == "" { log.Fatalf("%v returns an empty Type", jsonSubSchema.Items.SourceURL) } typ = subType + "[]" classDefinition = subClassDefinition } else { if refSubSchema := jsonSubSchema.Items.RefSubSchema; refSubSchema != nil { if refSubSchema.TypeName == "" { log.Fatalf("%v has not set TypeName", refSubSchema.SourceURL) } typ = refSubSchema.TypeName + "[]" } } } else { typ = "Object[]" } case "object": if s := jsonSubSchema.Properties; s != nil { typ = jsonSubSchema.TypeName classDefinition = "\n" + strings.Repeat(" ", level) + "public class " + typ + " {" for _, j := range s.SortedPropertyNames { // recursive call to build go types inside structs var subType string c := JsonSubSchema(*s.Properties[j]) subMember := s.MemberNames[j] subClassDefinition, subComment, subType := (&c).TypeDefinition(level+1, extraPackages) classDefinition += "\n" classDefinition += subClassDefinition classDefinition += "\n" classDefinition += utils.Indent(subComment, strings.Repeat(" ", level+1), false) classDefinition += strings.Repeat(" ", level+1) + "public " + subType + " " + subMember + ";" } classDefinition += "\n" classDefinition += strings.Repeat(" ", level) + "}" classDefinition += "\n" } else { typ = "Object" } case "number": typ = "int" case "integer": typ = "int" case "boolean": typ = "boolean" // json type string maps to go type string, so only need to test case of when // string is a json date-time, so we can convert to go type time.Time... case "string": if f := jsonSubSchema.Format; f != nil && *f == "date-time" { typ = "Date" } else { typ = "String" } } switch typ { case "Date": extraPackages["java.util.Date"] = true } return classDefinition, comment, typ }