middleware_update_relation.go 12 KB

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