middleware_delete.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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)
  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. // Nome do metodo que verifica se a entidade tem dependencias
  132. out, _ := TemplateToString(deleteStmtsTmpl, context)
  133. afterMethod := ctx.Statement.Block(G.Id(out)).Line()
  134. if createDepFunc {
  135. out, _ = TemplateToString(hasDepDeleteStmtsTmpl, context)
  136. afterMethod.Id(out)
  137. }
  138. return nil
  139. },
  140. }
  141. )
  142. // afterDefineDelete.Do(func(x *G.Statement) {
  143. // x.Add(G.Comment(
  144. // fmt.Sprintf("%s verifica se a entidade '%s' possui dependencias com outras entidades.", dependenceMethod, method.Entity),
  145. // ).Line())
  146. // // Cria as variaveis
  147. // block := G.Func().Id(dependenceMethod).Params(
  148. // G.Id("f").Op("*").Qual(API_URL, "Filter"),
  149. // ).Bool().BlockFunc(func(b *G.Group) {
  150. // for index, relation := range relations {
  151. // // for index, _ := range relations {
  152. // indexStr = strconv.Itoa(index)
  153. // cIndex = "c" + indexStr
  154. // xIndex = "x" + indexStr
  155. // // Cria o canal para a variavel
  156. // vars = append(vars, G.Id(cIndex).Op("=").Id("make").Call(G.Chan().Bool()))
  157. // // Define um case para um canal
  158. // cases = append(cases, G.Case(G.Id(xIndex).Op(":=").Op("<-").Id("c"+indexStr)).Block(
  159. // G.If(G.Id(xIndex)).Block(G.Return(G.True())),
  160. // ))
  161. // rotines = append(rotines, G.Go().Func().Params().Block(
  162. // G.Id("filter").Op(":=").Op("&").Qual(API_URL, "Filter").Values(G.Dict{
  163. // // Especifica a collection
  164. // G.Id("DB"): G.Lit(relation.DB),
  165. // G.Id("Collection"): G.Lit(relation.Collection),
  166. // // Especifica a query
  167. // G.Id("Query"): G.Op("&").Qual(BSON, "M").Values(G.Dict{
  168. // G.Lit(relation.Attr + "._id"): G.Id("f").Dot("Id"),
  169. // }),
  170. // }),
  171. // G.Id(cIndex).Op("<-").Id("Models").Dot("Exist").Call(G.Id("filter")),
  172. // ).Call().Line())
  173. // }
  174. // // Adiciona as variaveis de canal
  175. // b.Add(G.Var().DefsFunc(func(b2 *G.Group) {
  176. // // Gera o case para cada relacao
  177. // for _, v := range vars {
  178. // b2.Add(v)
  179. // }
  180. // }))
  181. // // Adiciona as chamadas das rotinas que consultam a existencia de dependencia
  182. // for _, r := range rotines {
  183. // // fmt.Printf("%#v", r)
  184. // b.Add(r)
  185. // }
  186. // // Geracao do for select
  187. // b.Add(G.For(
  188. // G.Id("i").Op(":=").Lit(0),
  189. // G.Id("i").Op("<").Lit(relationCount),
  190. // G.Id("i").Op("++"),
  191. // ).Block(G.Select().BlockFunc(func(b1 *G.Group) {
  192. // // Gera o case para cada relacao
  193. // for _, case1 := range cases {
  194. // b1.Add(case1)
  195. // }
  196. // })).Line())
  197. // b.Return(G.False())
  198. // // fmt.Printf("%#v")
  199. // })
  200. // x.Add(block)
  201. // }).Line()
  202. // if {
  203. // createDepFunc = true
  204. // do.Add(G.If(G.Id(dependenceMethod).Call(
  205. // G.Id("filter"),
  206. // )).Block(
  207. // G.Id("err").Op("=").Qual(API_URL, "Error").Call(
  208. // G.Qual(API_URL, "ERR_CONFLICT"),
  209. // G.Lit(fmt.Sprintf("Ocorreu um conflito ao remover a entidade '%s'", method.Entity)),
  210. // ),
  211. // G.Return(),
  212. // ).Line())
  213. // }
  214. // ctx.Statement.Block(
  215. // G.Id(`filter := ctx.Values.Get("$filter")`).Assert(G.Op("*").Qual(API_URL, "Filter")).Line(),
  216. // G.Id("filter").Dot("DB").Op("=").Lit(dbName),
  217. // G.Id("filter").Dot("Collection").Op("=").Lit(collectionName).Line(),
  218. // // Verifica se o tem tem dependencias
  219. // G.Do(func(do *G.Statement) {
  220. // if SR.Has(method.Entity) {
  221. // createDepFunc = true
  222. // do.Add(G.If(G.Id(dependenceMethod).Call(
  223. // G.Id("filter"),
  224. // )).Block(
  225. // G.Id("err").Op("=").Qual(API_URL, "Error").Call(
  226. // G.Qual(API_URL, "ERR_CONFLICT"),
  227. // G.Lit(fmt.Sprintf("Ocorreu um conflito ao remover a entidade '%s'", method.Entity)),
  228. // ),
  229. // G.Return(),
  230. // ).Line())
  231. // }
  232. // // fmt.Println("GenerateFunc" + method.Entity + "|" + dependenceMethod)
  233. // }),
  234. // G.Do(func(s *G.Statement) {
  235. // if method.BeforePersistAction {
  236. // fnName := fmt.Sprintf("Before%s%s", strings.Title(method.ID), method.Entity)
  237. // s.Add(G.Id(fmt.Sprintf(`
  238. // // Chama uma função onde são descritas as ações executadas antes da entidade ser persistida.
  239. // if err = %s(ctx, resp); err != nil {
  240. // return
  241. // }
  242. // `, fnName)))
  243. // // part := s.Comment("").Line()
  244. // // part.If(
  245. // // G.List(G.Id("fn"), G.Id("err")).Op("=").Id(fnName).Call(G.Id("ctx"), G.Id("patchs")),
  246. // // G.Id("err").Op("!=").Id("nil"),
  247. // // ).Block(G.Return())
  248. // }
  249. // }),
  250. // // Executa a remocao do item
  251. // // G.If(
  252. // // G.List(G.Id("_"), G.Id("err")).Op("=").Id("Models").Dot("RemoveOne").Call(
  253. // // G.Id("filter"),
  254. // // ),
  255. // G.Id(`
  256. // filter.Patchs = &`).Qual(BSON, "A").Id(`{
  257. // bson.M{
  258. // "$set": bson.M{
  259. // "deleted": true,
  260. // "deletedIn": `).Qual("time", "Now").Id(`().Unix(),
  261. // },
  262. // },
  263. // }`),
  264. // generateHookCall(project, method, "beforePersist"),
  265. // G.Id(`if _, err = models.Api.PatchOne(filter), err !`),
  266. // G.Return(),
  267. // // G.Return(G.Nil()),
  268. // ).
  269. // --------------------------------------------------
  270. // G.Id("err").Op("!=").Id("nil"),
  271. // ).Block(
  272. // G.Return(G.Id("err")),
  273. // G.Return(),
  274. // ),
  275. // G.Var().Defs(
  276. // G.Id("err").Op("*").Qual(API_ERROR, "Error"),
  277. // // G.Id("entity").Op("=").Op("&").Id(method.Entity).Values(),
  278. // ).Line(),
  279. // fmt.Println("Compont:" + method.Entity)
  280. // block.Add(
  281. // x.Var().Defs(
  282. // G.Id("err").Op("*").Qual(API_ERROR, "Error"),
  283. // G.Id("entity").Op("=").Op("&").Id(method.Entity).Values(),
  284. // ),
  285. // )
  286. // vars.Defs(varList...)