middleware_put.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. package got
  2. import (
  3. "text/template"
  4. . "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
  5. G "github.com/dave/jennifer/jen"
  6. )
  7. var (
  8. updateStmtsTmpl *template.Template
  9. updateStmtsErr error
  10. )
  11. func init() {
  12. updateStmtsTmpl, updateStmtsErr = ParseTemplate(`
  13. var (
  14. entity = &models.{{.entity}}Input{}
  15. )
  16. if err = api.ReadJson(ctx, entity); err != nil {
  17. return
  18. }
  19. entity.SetMode("update")
  20. if err = api.Validate(entity); err != nil {
  21. return
  22. }
  23. values := ctx.Values()
  24. entity.LastUpdate = api.NowUnix()
  25. user, hasUserRef := values.Get("$user.ref").(*models.UserReference)
  26. if hasUserRef {
  27. entity.UpdatedBy = user
  28. }
  29. values.Set("entity", entity)
  30. {{if .preconditions}}
  31. if _, err = executeAction(
  32. ctx,
  33. {{.preconditions}},
  34. ); err != nil {
  35. return
  36. }
  37. {{end}}
  38. filter := values.Get("$filter").(*api.Filter)
  39. filter.DB = "{{.dbName}}"
  40. filter.Collection = "{{.collectionName}}"
  41. filter.Entity = entity
  42. {{if .beforePersist}} if err = BeforePersist{{.entity}}Update(ctx, resp); err != nil {
  43. return
  44. }{{end}}
  45. if _, err = models.Api.UpdateOne(filter); err != nil {
  46. return
  47. }
  48. {{if .hasUpdateRelation}} // Cria uma thread que executa a atualizaca das referências.
  49. go func() {
  50. UpdateRelation{{.entity}}(filter)
  51. }() {{end}}
  52. {{if .beforeResponse}}
  53. if resp, err = executeAction(
  54. ctx,
  55. {{.beforeResponse}},
  56. ); err != nil || resp != nil {
  57. return
  58. }
  59. {{end}}
  60. resp = entity
  61. return`)
  62. if updateStmtsErr != nil {
  63. panic(updateStmtsErr)
  64. }
  65. }
  66. var (
  67. GenUpdateStmts = &Middleware{
  68. Id: "implement",
  69. Type: "method",
  70. Fn: func(ctx *MiddlewareContext) error {
  71. var (
  72. project = ctx.Project
  73. method = ctx.Method
  74. dbName = project.GetEntityDB(method.Entity)
  75. collectionName = project.GetCollection(method.Entity)
  76. dependenceMethod = BASE_HAS_DEPENDE + method.Entity
  77. beforeSend = method.Hook("beforeSend")
  78. beforePersist = method.Hook("beforePersist")
  79. relations = []map[string]interface{}{}
  80. context = map[string]interface{}{
  81. "dbName": dbName,
  82. "collectionName": collectionName,
  83. "entity": method.Entity,
  84. "dependenceMethod": dependenceMethod,
  85. "beforeSend": beforeSend,
  86. "beforePersist": beforePersist,
  87. "relations": &relations,
  88. "hasUpdateRelation": SR.Has(method.Entity),
  89. "preconditions": parseMethodActions(method.Preconditions),
  90. "beforeResponse": parseMethodActions(method.BeforeResponse),
  91. }
  92. )
  93. generateHookCall(project, method, "beforePersist")
  94. generateHookCall(project, method, "beforeSend")
  95. // Nome do metodo que verifica se a entidade tem dependencias
  96. out, _ := TemplateToString(updateStmtsTmpl, context)
  97. afterMethod := ctx.Statement.Block(G.Id(out)).Line()
  98. if body, err := createUpdateRelationMethod(method, context); err == nil {
  99. afterMethod.Id(body)
  100. }
  101. return nil
  102. },
  103. }
  104. )
  105. // updateRelationStmtsTmpl, updateStmtsErr = ParseTemplate(`
  106. // func UpdateRelation{{.entity}}(options *api.Filter) {
  107. // var (
  108. // filter *api.Filter
  109. // err *errs.Error
  110. // entity = &{{.entity}}Reference{}
  111. // wg = sync.WaitGroup{}
  112. // )
  113. // options.Entity = entity
  114. // if _, err = models.Api.FindOne(options); err != nil {
  115. // return
  116. // }
  117. // entity.Id = entity.Id.(primitive.ObjectID).Hex()
  118. // {{range .relations}}
  119. // wg.Add(1)
  120. // go func(){
  121. // defer wg.Done()
  122. // filter = &api.Filter{
  123. // Collection: "{{.Collection}}",
  124. // DB: "{{.DB}}",
  125. // Patchs: &bson.A{bson.M{"$set": bson.M{"{{.path}}": entity}}},
  126. // Query: &bson.M{"{{.attr}}._id": entity.Id},
  127. // }
  128. // if _, err = models.Api.PatchMany(filter); err != nil {
  129. // fmt.Println(err.Error())
  130. // }
  131. // }()
  132. // {{end}}
  133. // wg.Wait()
  134. // }`)
  135. // if updateStmtsErr != nil {
  136. // panic(updateStmtsErr)
  137. // }
  138. // if hasUpdateRelation && !updateRelationMethodDefined {
  139. // relationFunctionDefined[updRelation] = true
  140. // for _, relation := range SR.Get(method.Entity) {
  141. // if relation.DB == "" || relation.Collection == "" {
  142. // api.LogWarning(0, fmt.Sprintf("Relation DB or Collection can't be empty! %s -> %s", relation.Target, relation.Source))
  143. // continue
  144. // }
  145. // relations = append(relations, map[string]interface{}{
  146. // "DB": relation.DB,
  147. // "Collection": relation.Collection,
  148. // "attr": relation.Attr,
  149. // "path": fmt.Sprintf("%s%s", relation.Attr, indexMap[relation.IsArray]),
  150. // })
  151. // }
  152. // out, _ = TemplateToString(updateRelationStmtsTmpl, context)
  153. // afterMethod.Id(out)
  154. // }
  155. // j = G.Id("filter").Op("=").Op("&").Qual(API_URL, "Filter").Values(G.Dict{
  156. // // Especifica a collection
  157. // G.Id("DB"): G.Lit(relation.DB),
  158. // G.Id("Collection"): G.Lit(relation.Collection),
  159. // // Especifica a query
  160. // G.Id("Query"): G.Op("&").Qual(BSON, "M").Values(G.Dict{
  161. // G.Lit(attrId + "._id"): G.Id("f").Dot("Id").Dot("Hex").Call(),
  162. // }),
  163. // // G.Id("Entity"): G.Qual(BSON, "M").Values(G.Dict{
  164. // // G.Lit("$set"): G.Qual(BSON, "M").Values(G.Dict{
  165. // // G.Lit(attrId + index): G.Id("f").Dot("Entity"),
  166. // // }),
  167. // // }),
  168. // G.Id("Patchs"): G.Op("&").Qual(BSON, "A").Values(
  169. // G.Qual(BSON, "M").Values(G.Dict{
  170. // G.Lit("$set"): G.Qual(BSON, "M").Values(G.Dict{
  171. // G.Lit(attrId + index): G.Id("f").Dot("Entity"),
  172. // }),
  173. // }),
  174. // ),
  175. // }).Line().If(
  176. // G.List(G.Id("_"), G.Id("err")).Op("=").Id("Models").Dot("PatchMany").Call(
  177. // G.Id("filter"),
  178. // ),
  179. // G.Id("err").Op("!=").Id("nil"),
  180. // ).Block(
  181. // G.Qual("fmt", "Println").Call(G.Id("err").Dot("Error").Call()),
  182. // ).Line().Line()
  183. // k.Add(j)
  184. // .Do(func(s *G.Statement) {
  185. // _, found := relationFunctionDefined[updRelation]
  186. // if !createUpdateRelation || found {
  187. // return
  188. // }
  189. // s.Comment(updRelation + " atualiza as referências da entidade " + method.Entity).Line()
  190. // s.Func().Id(updRelation).Params(
  191. // G.Id("f").Op("*").Qual(API_URL, "Filter"),
  192. // ).Block(
  193. // G.Var().Defs(
  194. // G.Id("filter").Op("*").Qual(API_URL, "Filter"),
  195. // G.Id("err").Op("*").Qual(API_ERROR, "Error"),
  196. // ),
  197. // // atualiza o filtro para a entidade de referencia
  198. // G.Id("f").Dot("Entity").Op("=").Op("&").Id(method.Entity+"Reference").Values(),
  199. // // Carrega os dados do banco para atualizar nas entidades relacionadas
  200. // G.If(
  201. // G.List(G.Id("_"), G.Id("err")).Op("=").Id("Models").Dot("FindOne").Call(
  202. // G.Id("f"),
  203. // ),
  204. // G.Id("err").Op("!=").Id("nil"),
  205. // ).Block(
  206. // G.Return(),
  207. // ),
  208. // G.Do(func(k *G.Statement) { // Adiciona as regras de atualizacao
  209. // var (
  210. // j *G.Statement
  211. // index string
  212. // )
  213. // for _, relation := range SR.Get(method.Entity) {
  214. // if relation.DB == "" || relation.Collection == "" {
  215. // api.LogWarning(0, fmt.Sprintf("Relation DB or Collection can't be empty! %s -> %s", relation.Target, relation.Source))
  216. // continue
  217. // }
  218. // // spew.Dump(relation)
  219. // // panic("sss")
  220. // // e := project.GetSchema(relation)
  221. // attrId := relation.Attr
  222. // if relation.IsArray {
  223. // index = ".$"
  224. // } else {
  225. // index = ""
  226. // }
  227. // j = G.Id("filter").Op("=").Op("&").Qual(API_URL, "Filter").Values(G.Dict{
  228. // // Especifica a collection
  229. // G.Id("DB"): G.Lit(relation.DB),
  230. // G.Id("Collection"): G.Lit(relation.Collection),
  231. // // Especifica a query
  232. // G.Id("Query"): G.Op("&").Qual(BSON, "M").Values(G.Dict{
  233. // G.Lit(attrId + "._id"): G.Id("f").Dot("Id").Dot("Hex").Call(),
  234. // }),
  235. // // G.Id("Entity"): G.Qual(BSON, "M").Values(G.Dict{
  236. // // G.Lit("$set"): G.Qual(BSON, "M").Values(G.Dict{
  237. // // G.Lit(attrId + index): G.Id("f").Dot("Entity"),
  238. // // }),
  239. // // }),
  240. // G.Id("Patchs"): G.Op("&").Qual(BSON, "A").Values(
  241. // G.Qual(BSON, "M").Values(G.Dict{
  242. // G.Lit("$set"): G.Qual(BSON, "M").Values(G.Dict{
  243. // G.Lit(attrId + index): G.Id("f").Dot("Entity"),
  244. // }),
  245. // }),
  246. // ),
  247. // }).Line().If(
  248. // G.List(G.Id("_"), G.Id("err")).Op("=").Id("Models").Dot("PatchMany").Call(
  249. // G.Id("filter"),
  250. // ),
  251. // G.Id("err").Op("!=").Id("nil"),
  252. // ).Block(
  253. // G.Qual("fmt", "Println").Call(G.Id("err").Dot("Error").Call()),
  254. // ).Line().Line()
  255. // k.Add(j)
  256. // }
  257. // }),
  258. // )
  259. // })
  260. // var (
  261. // // UpdateRelationRotine *G.Statement
  262. // method = ctx.Method
  263. // project = ctx.Project
  264. // updRelation = UPDATE_RELATION + method.Entity
  265. // createUpdateRelation = false
  266. // entity = method.Request
  267. // responseEntity = GenericPart.ReplaceAllString(method.Response, "")
  268. // )
  269. // if entity == "" {
  270. // panic("Modelo de request não definido em UpdateStmt!")
  271. // }
  272. // if responseEntity == "" {
  273. // panic("Modelo de response não definido!")
  274. // }
  275. // ctx.Statement.Block(
  276. // // Declaracao das variaveis
  277. // G.Var().Defs(
  278. // // G.Id("err").Op("*").Qual(API_ERROR, "Error"),
  279. // G.Id("entity").Op("=").Op("&").Id(entity).Values(),
  280. // ).Line(),
  281. // // Fazendo o parse do body
  282. // G.If(
  283. // G.Id("err").Op("=").Qual(API_URL, "ReadJson").Call(G.Id("ctx"), G.Id("entity")),
  284. // G.Id("err").Op("!=").Id("nil"),
  285. // ).Block(
  286. // // G.Id("api").Dot("Falha").Call(
  287. // // G.Id("ctx"),
  288. // // G.Id("api").Dot("ErrGeneral"),
  289. // // G.Id("err").Dot("Error").Call(),
  290. // // G.Nil(),
  291. // // ),
  292. // // G.Return(G.Id("err")),
  293. // G.Return(),
  294. // ),
  295. // G.Do(func(s *G.Statement) {
  296. // entity := ctx.Project.EntityDesc(method.Entity)
  297. // if entity != nil && entity.HasMode {
  298. // s.Add(G.Id(`entity.SetMode("create")`))
  299. // }
  300. // }),
  301. // G.If(
  302. // G.Id("err").Op("=").Qual(API_URL, "Validate").Call(G.Id("entity")),
  303. // G.Id("err").Op("!=").Id("nil"),
  304. // ).Block(
  305. // // G.Return(G.Id("err")),
  306. // G.Return(),
  307. // ).Line(),
  308. // // Captura a base de values
  309. // G.Id("values").Op(":=").Id("ctx").Dot("Values").Call(),
  310. // // Gera as atribuicoes de variaveis que seram atualizadas (usuario e ultimo update quando existir)
  311. // G.Do(func(part *G.Statement) {
  312. // entity := ctx.Project.GetSchema(method.Entity)
  313. // user := false
  314. // for _, prop := range entity.Properties {
  315. // if def, ok := prop.Autogenerate["update"]; ok {
  316. // switch def.Type {
  317. // case "user":
  318. // if !user {
  319. // part.Add(G.Id(`user := values.Get("$user.ref").(*UserReference)`).Line())
  320. // user = true
  321. // }
  322. // part.Add(G.Id("entity").Dot(strings.Title(prop.ID)).Op("=").Id("user").Line())
  323. // case "now":
  324. // part.Add(G.Id("entity").Dot(strings.Title(prop.ID)).Op("=").Qual("time", "Now").Call().Id(".Unix()").Line())
  325. // }
  326. // }
  327. // }
  328. // }).Line(),
  329. // // Carrega o filtro do contexto para adicionar a entidade
  330. // G.Id("filter").Op(":=").Id("values").Dot("Get").Call(
  331. // G.Lit("$filter"),
  332. // ).Assert(G.Op("*").Qual(API_URL, "Filter")).Line(),
  333. // // Adiciona a entidade
  334. // G.Id("filter").Dot("DB").Op("=").Lit(ctx.Project.GetEntityDB(method.Entity)),
  335. // G.Id("filter").Dot("Collection").Op("=").Lit(ctx.Project.GetCollection(method.Entity)),
  336. // G.Id("filter").Dot("Entity").Op("=").Id("entity").Line(),
  337. // generateHookCall(project, method, "beforePersist"),
  338. // // Inseri a entidade na coleção e verifica se a operação ocorreu com exito
  339. // G.If(
  340. // G.List(G.Id("_"), G.Id("err")).Op("=").Id("Models").Dot("UpdateOne").Call(
  341. // // G.Lit(ctx.Project.GetCollection(method.Entity)),
  342. // G.Id("filter"),
  343. // ),
  344. // G.Id("err").Op("!=").Id("nil"),
  345. // ).Block(
  346. // // G.Id("api").Dot("Falha").Call(
  347. // // G.Id("ctx"),
  348. // // G.Id("api").Dot("ErrGeneral"),
  349. // // G.Id("err").Dot("Error").Call(),
  350. // // G.Nil(),
  351. // // ),
  352. // // bson.IsObjectIdHex(m.Id.Hex())
  353. // // G.Return(G.Id("err")),
  354. // G.Return(),
  355. // ),
  356. // // Cria a rotina de atualização de relacionamentos
  357. // G.Do(func(s *G.Statement) {
  358. // if SR.Has(method.Entity) {
  359. // createUpdateRelation = true
  360. // relationFunctionDefined[updRelation] = true
  361. // s.Comment("Cria uma thread que executa a atualizaca das referências.").Line().Go().Func().Params().Block(
  362. // G.Id(updRelation).Call(G.Id("filter")),
  363. // ).Call()
  364. // }
  365. // }),
  366. // // Envia a resposta pro usuario em caso de sucesso
  367. // // G.Line().Id("resp").Op("=").Id(responseEntity).Values(G.Dict{
  368. // // G.Id("Entity"): G.Id("entity"),
  369. // // }),
  370. // G.Line().Id("resp").Op("=").Id("entity"),
  371. // generateHookCall(project, method, "beforeSend"),
  372. // // G.Return(G.Nil()),
  373. // G.Return(),
  374. // ).Line()