genpacket.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package javagen
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "io"
  7. "os"
  8. "strings"
  9. "text/template"
  10. "github.com/tal-tech/go-zero/core/stringx"
  11. "github.com/tal-tech/go-zero/tools/goctl/api/spec"
  12. apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
  13. "github.com/tal-tech/go-zero/tools/goctl/util"
  14. )
  15. const packetTemplate = `package com.xhb.logic.http.packet.{{.packet}};
  16. import com.google.gson.Gson;
  17. import com.xhb.commons.JSON;
  18. import com.xhb.commons.JsonMarshal;
  19. import com.xhb.core.network.HttpRequestClient;
  20. import com.xhb.core.packet.HttpRequestPacket;
  21. import com.xhb.core.response.HttpResponseData;
  22. import com.xhb.logic.http.DeProguardable;
  23. {{if not .HasRequestBody}}
  24. import com.xhb.logic.http.request.EmptyRequest;
  25. {{end}}
  26. {{.import}}
  27. import org.jetbrains.annotations.NotNull;
  28. import org.jetbrains.annotations.Nullable;
  29. import org.json.JSONObject;
  30. public class {{.packetName}} extends HttpRequestPacket<{{.packetName}}.{{.packetName}}Response> {
  31. {{.paramsDeclaration}}
  32. public {{.packetName}}({{.params}}{{if .HasRequestBody}}, {{.requestType}} request{{end}}) {
  33. {{if .HasRequestBody}}super(request);{{else}}super(EmptyRequest.instance);{{end}}
  34. {{if .HasRequestBody}}this.request = request;{{end}}{{.paramsSet}}
  35. }
  36. @Override
  37. public HttpRequestClient.Method requestMethod() {
  38. return HttpRequestClient.Method.{{.method}};
  39. }
  40. @Override
  41. public String requestUri() {
  42. return {{.uri}};
  43. }
  44. @Override
  45. public {{.packetName}}Response newInstanceFrom(JSON json) {
  46. return new {{.packetName}}Response(json);
  47. }
  48. public static class {{.packetName}}Response extends HttpResponseData {
  49. private {{.responseType}} responseData;
  50. {{.packetName}}Response(@NotNull JSON json) {
  51. super(json);
  52. JSONObject jsonObject = json.asObject();
  53. if (JsonParser.hasKey(jsonObject, "data")) {
  54. Gson gson = new Gson();
  55. JSONObject dataJson = JsonParser.getJSONObject(jsonObject, "data");
  56. responseData = gson.fromJson(dataJson.toString(), {{.responseType}}.class);
  57. }
  58. }
  59. public {{.responseType}} get{{.responseType}} () {
  60. return responseData;
  61. }
  62. }
  63. {{.types}}
  64. }
  65. `
  66. func genPacket(dir, packetName string, api *spec.ApiSpec) error {
  67. for _, route := range api.Service.Routes() {
  68. if err := createWith(dir, api, route, packetName); err != nil {
  69. return err
  70. }
  71. }
  72. return nil
  73. }
  74. func createWith(dir string, api *spec.ApiSpec, route spec.Route, packetName string) error {
  75. packet, ok := apiutil.GetAnnotationValue(route.Annotations, "server", "handler")
  76. packet = strings.Replace(packet, "Handler", "Packet", 1)
  77. if !ok {
  78. return fmt.Errorf("missing packet annotation for %q", route.Path)
  79. }
  80. javaFile := packet + ".java"
  81. fp, created, err := apiutil.MaybeCreateFile(dir, "", javaFile)
  82. if err != nil {
  83. return err
  84. }
  85. if !created {
  86. return nil
  87. }
  88. defer fp.Close()
  89. var builder strings.Builder
  90. var first bool
  91. tps := apiutil.GetLocalTypes(api, route)
  92. for _, tp := range tps {
  93. if first {
  94. first = false
  95. } else {
  96. fmt.Fprintln(&builder)
  97. }
  98. if err := genType(&builder, tp, api.Types); err != nil {
  99. return err
  100. }
  101. }
  102. types := builder.String()
  103. writeIndent(&builder, 1)
  104. params := paramsForRoute(route)
  105. paramsDeclaration := declarationForRoute(route)
  106. paramsSet := paramsSet(route)
  107. t := template.Must(template.New("packetTemplate").Parse(packetTemplate))
  108. var tmplBytes bytes.Buffer
  109. err = t.Execute(&tmplBytes, map[string]interface{}{
  110. "packetName": packet,
  111. "method": strings.ToUpper(route.Method),
  112. "uri": processUri(route),
  113. "types": strings.TrimSpace(types),
  114. "responseType": stringx.TakeOne(util.Title(route.ResponseType.Name), "Object"),
  115. "params": params,
  116. "paramsDeclaration": strings.TrimSpace(paramsDeclaration),
  117. "paramsSet": paramsSet,
  118. "packet": packetName,
  119. "requestType": util.Title(route.RequestType.Name),
  120. "HasRequestBody": len(route.RequestType.GetBodyMembers()) > 0,
  121. "import": getImports(api, route, packetName),
  122. })
  123. if err != nil {
  124. return err
  125. }
  126. formatFile(&tmplBytes, fp)
  127. return nil
  128. }
  129. func getImports(api *spec.ApiSpec, route spec.Route, packetName string) string {
  130. var builder strings.Builder
  131. allTypes := apiutil.GetAllTypes(api, route)
  132. sharedTypes := apiutil.GetSharedTypes(api)
  133. for _, at := range allTypes {
  134. for _, item := range sharedTypes {
  135. if item.Name == at.Name {
  136. fmt.Fprintf(&builder, "import com.xhb.logic.http.packet.%s.model.%s;\n", packetName, item.Name)
  137. break
  138. }
  139. }
  140. }
  141. return builder.String()
  142. }
  143. func formatFile(tmplBytes *bytes.Buffer, file *os.File) {
  144. scanner := bufio.NewScanner(tmplBytes)
  145. builder := bufio.NewWriter(file)
  146. defer builder.Flush()
  147. preIsBreakLine := false
  148. for scanner.Scan() {
  149. text := strings.TrimSpace(scanner.Text())
  150. if text == "" && preIsBreakLine {
  151. continue
  152. }
  153. preIsBreakLine = text == ""
  154. builder.WriteString(scanner.Text() + "\n")
  155. }
  156. if err := scanner.Err(); err != nil {
  157. fmt.Println(err)
  158. }
  159. }
  160. func paramsSet(route spec.Route) string {
  161. path := route.Path
  162. cops := strings.Split(path, "/")
  163. var builder strings.Builder
  164. for _, cop := range cops {
  165. if len(cop) == 0 {
  166. continue
  167. }
  168. if strings.HasPrefix(cop, ":") {
  169. param := cop[1:]
  170. builder.WriteString("\n")
  171. builder.WriteString(fmt.Sprintf("\t\tthis.%s = %s;", param, param))
  172. }
  173. }
  174. result := builder.String()
  175. return result
  176. }
  177. func paramsForRoute(route spec.Route) string {
  178. path := route.Path
  179. cops := strings.Split(path, "/")
  180. var builder strings.Builder
  181. for _, cop := range cops {
  182. if len(cop) == 0 {
  183. continue
  184. }
  185. if strings.HasPrefix(cop, ":") {
  186. builder.WriteString(fmt.Sprintf("String %s, ", cop[1:]))
  187. }
  188. }
  189. return strings.TrimSuffix(builder.String(), ", ")
  190. }
  191. func declarationForRoute(route spec.Route) string {
  192. path := route.Path
  193. cops := strings.Split(path, "/")
  194. var builder strings.Builder
  195. writeIndent(&builder, 1)
  196. for _, cop := range cops {
  197. if len(cop) == 0 {
  198. continue
  199. }
  200. if strings.HasPrefix(cop, ":") {
  201. writeIndent(&builder, 1)
  202. builder.WriteString(fmt.Sprintf("private String %s;\n", cop[1:]))
  203. }
  204. }
  205. result := strings.TrimSpace(builder.String())
  206. if len(result) > 0 {
  207. result = "\n" + result
  208. }
  209. return result
  210. }
  211. func processUri(route spec.Route) string {
  212. path := route.Path
  213. var builder strings.Builder
  214. cops := strings.Split(path, "/")
  215. for index, cop := range cops {
  216. if len(cop) == 0 {
  217. continue
  218. }
  219. if strings.HasPrefix(cop, ":") {
  220. builder.WriteString("/\" + " + cop[1:] + " + \"")
  221. } else {
  222. builder.WriteString("/" + cop)
  223. if index == len(cops)-1 {
  224. builder.WriteString("\"")
  225. }
  226. }
  227. }
  228. result := builder.String()
  229. if strings.HasSuffix(result, " + \"") {
  230. result = result[:len(result)-4]
  231. }
  232. if strings.HasPrefix(result, "/") {
  233. result = "\"" + result
  234. }
  235. return result
  236. }
  237. func genType(writer io.Writer, tp spec.Type, types []spec.Type) error {
  238. if len(tp.GetBodyMembers()) == 0 {
  239. return nil
  240. }
  241. writeIndent(writer, 1)
  242. fmt.Fprintf(writer, "static class %s implements DeProguardable {\n", util.Title(tp.Name))
  243. var members []spec.Member
  244. err := writeMembers(writer, types, tp.Members, &members, 2)
  245. if err != nil {
  246. return err
  247. }
  248. writeNewline(writer)
  249. writeIndent(writer, 1)
  250. genGetSet(writer, members, 2)
  251. writeIndent(writer, 1)
  252. fmt.Fprintln(writer, "}")
  253. return nil
  254. }