genpacket.go 6.8 KB

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