middleware_delete.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. package got
  2. import (
  3. "text/template"
  4. . "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
  5. G "github.com/dave/jennifer/jen"
  6. )
  7. const ()
  8. var (
  9. deleteStmtsTmpl, hasDepDeleteStmtsTmpl *template.Template
  10. deleteStmtsErr error
  11. )
  12. func init() {
  13. deleteStmtsTmpl, deleteStmtsErr = ParseTemplate(`
  14. var (
  15. values = ctx.Values()
  16. )
  17. values.Set("hard.deletion", {{.hardDeletion}})
  18. filter := values.Get("$filter").(*api.Filter)
  19. filter.DB = "{{.dbName}}"
  20. filter.Collection = "{{.collectionName}}"
  21. {{if .createDepFunc}}
  22. if HasDep{{.entity}}(filter) {
  23. err = errs.FailedPrecondition().Details(&errs.Detail{
  24. Message: "Ocorreu um conflito ao remover a entidade '{{.entity}}'",
  25. })
  26. return
  27. }
  28. {{end}}
  29. {{if .preconditions}}
  30. if _, err = executeAction(
  31. ctx,
  32. {{.preconditions}},
  33. ); err != nil {
  34. return
  35. }
  36. {{end}}
  37. if hardDeletion, _ := values.GetBool("hard.deletion"); hardDeletion {
  38. _, err = models.Api.RemoveOne(filter)
  39. } else {
  40. if replacement := values.Get("replace.default.patch"); replacement != nil {
  41. filter.Patchs = replacement.(*bson.A)
  42. } else {
  43. filter.Patchs = api.DeletedPatch()
  44. }
  45. _, err = models.Api.PatchOne(filter)
  46. }
  47. if err != nil {
  48. err.Details(&errs.Detail{
  49. Dominio: "",
  50. Reason: "",
  51. Location: "middleware.path",
  52. LocationType: "middleware.operation",
  53. })
  54. }
  55. {{if .beforeResponse}}
  56. if resp, err = executeAction(
  57. ctx,
  58. {{.beforeResponse}},
  59. ); err != nil || resp != nil {
  60. return
  61. }
  62. {{end}}
  63. resp = ""
  64. return`)
  65. if deleteStmtsErr != nil {
  66. panic(deleteStmtsErr)
  67. }
  68. hasDepDeleteStmtsTmpl, deleteStmtsErr = ParseTemplate(`
  69. // {{.dependenceMethod}} verifica se a entidade '{{.entity}}' possui dependencias com outras entidades.
  70. func {{.dependenceMethod}}(options *api.Filter) bool {
  71. var (
  72. foundChan = make(chan bool)
  73. find = func(db, collection, attr string) {
  74. exists, _ := models.Api.Exists(&api.Filter{
  75. DB: db,
  76. Collection: collection,
  77. Query: &bson.M{attr: options.Id},
  78. })
  79. foundChan <- exists
  80. }
  81. )
  82. {{range .relations}}
  83. go find("{{.DB}}", "{{.Collection}}", "{{.Attr}}._id")
  84. {{end}}
  85. for i := 0; i < {{.relationCount}}; i++ {
  86. select {
  87. {{range $idx, $relation := .relations}} case x{{$idx}} := <-foundChan:
  88. if x{{$idx}} {
  89. return true
  90. }
  91. {{end}}
  92. }
  93. }
  94. return false
  95. }`)
  96. if deleteStmtsErr != nil {
  97. panic(deleteStmtsErr)
  98. }
  99. }
  100. var (
  101. GenDeleteStmts = &Middleware{
  102. Id: "delete",
  103. Type: "method",
  104. Fn: func(ctx *MiddlewareContext) error {
  105. var (
  106. project = ctx.Project
  107. method = ctx.Method
  108. dbName = project.GetEntityDB(method.Entity)
  109. collectionName = project.GetCollection(method.Entity)
  110. relations = SR.Get(method.Entity)
  111. relationCount = len(relations)
  112. dependenceMethod = BASE_HAS_DEPENDE + method.Entity
  113. createDepFunc = SR.Has(method.Entity) && dependenceMethodDeclared[method.Entity] != true
  114. beforeSend = method.Hook("beforeSend")
  115. beforePersist = method.Hook("beforePersist")
  116. context = map[string]interface{}{
  117. "dbName": dbName,
  118. "collectionName": collectionName,
  119. "entity": method.Entity,
  120. "createDepFunc": createDepFunc,
  121. "relationCount": relationCount,
  122. "relations": relations,
  123. "dependenceMethod": dependenceMethod,
  124. "beforePersist": beforePersist,
  125. "beforeSend": beforeSend,
  126. "hardDeletion": getCustom(method.Custom, "go.entiy.hard.deletion", false),
  127. "preconditions": parseMethodActions(method.Preconditions),
  128. "beforeResponse": parseMethodActions(method.BeforeResponse),
  129. }
  130. )
  131. dependenceMethodDeclared[method.Entity] = true
  132. // Nome do metodo que verifica se a entidade tem dependencias
  133. out, _ := TemplateToString(deleteStmtsTmpl, context)
  134. afterMethod := ctx.Statement.Block(G.Id(out)).Line()
  135. if createDepFunc {
  136. out, _ = TemplateToString(hasDepDeleteStmtsTmpl, context)
  137. afterMethod.Id(out)
  138. }
  139. return nil
  140. },
  141. }
  142. )
  143. // afterDefineDelete.Do(func(x *G.Statement) {
  144. // x.Add(G.Comment(
  145. // fmt.Sprintf("%s verifica se a entidade '%s' possui dependencias com outras entidades.", dependenceMethod, method.Entity),
  146. // ).Line())
  147. // // Cria as variaveis
  148. // block := G.Func().Id(dependenceMethod).Params(
  149. // G.Id("f").Op("*").Qual(API_URL, "Filter"),
  150. // ).Bool().BlockFunc(func(b *G.Group) {
  151. // for index, relation := range relations {
  152. // // for index, _ := range relations {
  153. // indexStr = strconv.Itoa(index)
  154. // cIndex = "c" + indexStr
  155. // xIndex = "x" + indexStr
  156. // // Cria o canal para a variavel
  157. // vars = append(vars, G.Id(cIndex).Op("=").Id("make").Call(G.Chan().Bool()))
  158. // // Define um case para um canal
  159. // cases = append(cases, G.Case(G.Id(xIndex).Op(":=").Op("<-").Id("c"+indexStr)).Block(
  160. // G.If(G.Id(xIndex)).Block(G.Return(G.True())),
  161. // ))
  162. // rotines = append(rotines, G.Go().Func().Params().Block(
  163. // G.Id("filter").Op(":=").Op("&").Qual(API_URL, "Filter").Values(G.Dict{
  164. // // Especifica a collection
  165. // G.Id("DB"): G.Lit(relation.DB),
  166. // G.Id("Collection"): G.Lit(relation.Collection),
  167. // // Especifica a query
  168. // G.Id("Query"): G.Op("&").Qual(BSON, "M").Values(G.Dict{
  169. // G.Lit(relation.Attr + "._id"): G.Id("f").Dot("Id"),
  170. // }),
  171. // }),
  172. // G.Id(cIndex).Op("<-").Id("Models").Dot("Exist").Call(G.Id("filter")),
  173. // ).Call().Line())
  174. // }
  175. // // Adiciona as variaveis de canal
  176. // b.Add(G.Var().DefsFunc(func(b2 *G.Group) {
  177. // // Gera o case para cada relacao
  178. // for _, v := range vars {
  179. // b2.Add(v)
  180. // }
  181. // }))
  182. // // Adiciona as chamadas das rotinas que consultam a existencia de dependencia
  183. // for _, r := range rotines {
  184. // // fmt.Printf("%#v", r)
  185. // b.Add(r)
  186. // }
  187. // // Geracao do for select
  188. // b.Add(G.For(
  189. // G.Id("i").Op(":=").Lit(0),
  190. // G.Id("i").Op("<").Lit(relationCount),
  191. // G.Id("i").Op("++"),
  192. // ).Block(G.Select().BlockFunc(func(b1 *G.Group) {
  193. // // Gera o case para cada relacao
  194. // for _, case1 := range cases {
  195. // b1.Add(case1)
  196. // }
  197. // })).Line())
  198. // b.Return(G.False())
  199. // // fmt.Printf("%#v")
  200. // })
  201. // x.Add(block)
  202. // }).Line()
  203. // if {
  204. // createDepFunc = true
  205. // do.Add(G.If(G.Id(dependenceMethod).Call(
  206. // G.Id("filter"),
  207. // )).Block(
  208. // G.Id("err").Op("=").Qual(API_URL, "Error").Call(
  209. // G.Qual(API_URL, "ERR_CONFLICT"),
  210. // G.Lit(fmt.Sprintf("Ocorreu um conflito ao remover a entidade '%s'", method.Entity)),
  211. // ),
  212. // G.Return(),
  213. // ).Line())
  214. // }
  215. // ctx.Statement.Block(
  216. // G.Id(`filter := ctx.Values.Get("$filter")`).Assert(G.Op("*").Qual(API_URL, "Filter")).Line(),
  217. // G.Id("filter").Dot("DB").Op("=").Lit(dbName),
  218. // G.Id("filter").Dot("Collection").Op("=").Lit(collectionName).Line(),
  219. // // Verifica se o tem tem dependencias
  220. // G.Do(func(do *G.Statement) {
  221. // if SR.Has(method.Entity) {
  222. // createDepFunc = true
  223. // do.Add(G.If(G.Id(dependenceMethod).Call(
  224. // G.Id("filter"),
  225. // )).Block(
  226. // G.Id("err").Op("=").Qual(API_URL, "Error").Call(
  227. // G.Qual(API_URL, "ERR_CONFLICT"),
  228. // G.Lit(fmt.Sprintf("Ocorreu um conflito ao remover a entidade '%s'", method.Entity)),
  229. // ),
  230. // G.Return(),
  231. // ).Line())
  232. // }
  233. // // fmt.Println("GenerateFunc" + method.Entity + "|" + dependenceMethod)
  234. // }),
  235. // G.Do(func(s *G.Statement) {
  236. // if method.BeforePersistAction {
  237. // fnName := fmt.Sprintf("Before%s%s", strings.Title(method.ID), method.Entity)
  238. // s.Add(G.Id(fmt.Sprintf(`
  239. // // Chama uma função onde são descritas as ações executadas antes da entidade ser persistida.
  240. // if err = %s(ctx, resp); err != nil {
  241. // return
  242. // }
  243. // `, fnName)))
  244. // // part := s.Comment("").Line()
  245. // // part.If(
  246. // // G.List(G.Id("fn"), G.Id("err")).Op("=").Id(fnName).Call(G.Id("ctx"), G.Id("patchs")),
  247. // // G.Id("err").Op("!=").Id("nil"),
  248. // // ).Block(G.Return())
  249. // }
  250. // }),
  251. // // Executa a remocao do item
  252. // // G.If(
  253. // // G.List(G.Id("_"), G.Id("err")).Op("=").Id("Models").Dot("RemoveOne").Call(
  254. // // G.Id("filter"),
  255. // // ),
  256. // G.Id(`
  257. // filter.Patchs = &`).Qual(BSON, "A").Id(`{
  258. // bson.M{
  259. // "$set": bson.M{
  260. // "deleted": true,
  261. // "deletedIn": `).Qual("time", "Now").Id(`().Unix(),
  262. // },
  263. // },
  264. // }`),
  265. // generateHookCall(project, method, "beforePersist"),
  266. // G.Id(`if _, err = models.Api.PatchOne(filter), err !`),
  267. // G.Return(),
  268. // // G.Return(G.Nil()),
  269. // ).
  270. // --------------------------------------------------
  271. // G.Id("err").Op("!=").Id("nil"),
  272. // ).Block(
  273. // G.Return(G.Id("err")),
  274. // G.Return(),
  275. // ),
  276. // G.Var().Defs(
  277. // G.Id("err").Op("*").Qual(API_ERROR, "Error"),
  278. // // G.Id("entity").Op("=").Op("&").Id(method.Entity).Values(),
  279. // ).Line(),
  280. // fmt.Println("Compont:" + method.Entity)
  281. // block.Add(
  282. // x.Var().Defs(
  283. // G.Id("err").Op("*").Qual(API_ERROR, "Error"),
  284. // G.Id("entity").Op("=").Op("&").Id(method.Entity).Values(),
  285. // ),
  286. // )
  287. // vars.Defs(varList...)