package got import ( "text/template" . "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common" G "github.com/dave/jennifer/jen" ) const () var ( deleteStmtsTmpl, hasDepDeleteStmtsTmpl *template.Template deleteStmtsErr error ) func init() { deleteStmtsTmpl, deleteStmtsErr = ParseTemplate(` var ( values = ctx.Values() ) values.Set("hard.deletion", {{.hardDeletion}}) filter := values.Get("$filter").(*api.Filter) filter.DB = "{{.dbName}}" filter.Collection = "{{.collectionName}}" {{if .createDepFunc}} if HasDep{{.entity}}(filter) { err = errs.FailedPrecondition().Details(&errs.Detail{ Message: "Ocorreu um conflito ao remover a entidade '{{.entity}}'", }) return } {{end}} {{if .preconditions}} if _, err = executeAction( ctx, {{.preconditions}}, ); err != nil { return } {{end}} if hardDeletion, _ := values.GetBool("hard.deletion"); hardDeletion { _, err = models.Api.RemoveOne(filter) } else { if replacement := values.Get("replace.default.patch"); replacement != nil { filter.Patchs = replacement.(*bson.A) } else { filter.Patchs = api.DeletedPatch() } _, err = models.Api.PatchOne(filter) } if err != nil { err.Details(&errs.Detail{ Dominio: "", Reason: "", Location: "middleware.path", LocationType: "middleware.operation", }) } {{if .beforeResponse}} if resp, err = executeAction( ctx, {{.beforeResponse}}, ); err != nil || resp != nil { return } {{end}} resp = "" return`) if deleteStmtsErr != nil { panic(deleteStmtsErr) } hasDepDeleteStmtsTmpl, deleteStmtsErr = ParseTemplate(` // {{.dependenceMethod}} verifica se a entidade '{{.entity}}' possui dependencias com outras entidades. func {{.dependenceMethod}}(options *api.Filter) bool { var ( foundChan = make(chan bool) find = func(db, collection, attr string) { exists, _ := models.Api.Exists(&api.Filter{ DB: db, Collection: collection, Query: &bson.M{attr: options.Id}, }) foundChan <- exists } ) {{range .relations}} go find("{{.DB}}", "{{.Collection}}", "{{.Attr}}._id") {{end}} for i := 0; i < {{.relationCount}}; i++ { select { {{range $idx, $relation := .relations}} case x{{$idx}} := <-foundChan: if x{{$idx}} { return true } {{end}} } } return false }`) if deleteStmtsErr != nil { panic(deleteStmtsErr) } } var ( GenDeleteStmts = &Middleware{ Id: "delete", Type: "method", Fn: func(ctx *MiddlewareContext) error { var ( project = ctx.Project method = ctx.Method dbName = project.GetEntityDB(method.Entity) collectionName = project.GetCollection(method.Entity) relations = SR.Get(method.Entity) relationCount = len(relations) dependenceMethod = BASE_HAS_DEPENDE + method.Entity createDepFunc = SR.Has(method.Entity) && dependenceMethodDeclared[method.Entity] != true beforeSend = method.Hook("beforeSend") beforePersist = method.Hook("beforePersist") context = map[string]interface{}{ "dbName": dbName, "collectionName": collectionName, "entity": method.Entity, "createDepFunc": createDepFunc, "relationCount": relationCount, "relations": relations, "dependenceMethod": dependenceMethod, "beforePersist": beforePersist, "beforeSend": beforeSend, "hardDeletion": getCustom(method.Custom, "go.entiy.hard.deletion", false), "preconditions": parseMethodActions(method.Preconditions), "beforeResponse": parseMethodActions(method.BeforeResponse), } ) dependenceMethodDeclared[method.Entity] = true // Nome do metodo que verifica se a entidade tem dependencias out, _ := TemplateToString(deleteStmtsTmpl, context) afterMethod := ctx.Statement.Block(G.Id(out)).Line() if createDepFunc { out, _ = TemplateToString(hasDepDeleteStmtsTmpl, context) afterMethod.Id(out) } return nil }, } ) // afterDefineDelete.Do(func(x *G.Statement) { // x.Add(G.Comment( // fmt.Sprintf("%s verifica se a entidade '%s' possui dependencias com outras entidades.", dependenceMethod, method.Entity), // ).Line()) // // Cria as variaveis // block := G.Func().Id(dependenceMethod).Params( // G.Id("f").Op("*").Qual(API_URL, "Filter"), // ).Bool().BlockFunc(func(b *G.Group) { // for index, relation := range relations { // // for index, _ := range relations { // indexStr = strconv.Itoa(index) // cIndex = "c" + indexStr // xIndex = "x" + indexStr // // Cria o canal para a variavel // vars = append(vars, G.Id(cIndex).Op("=").Id("make").Call(G.Chan().Bool())) // // Define um case para um canal // cases = append(cases, G.Case(G.Id(xIndex).Op(":=").Op("<-").Id("c"+indexStr)).Block( // G.If(G.Id(xIndex)).Block(G.Return(G.True())), // )) // rotines = append(rotines, G.Go().Func().Params().Block( // G.Id("filter").Op(":=").Op("&").Qual(API_URL, "Filter").Values(G.Dict{ // // Especifica a collection // G.Id("DB"): G.Lit(relation.DB), // G.Id("Collection"): G.Lit(relation.Collection), // // Especifica a query // G.Id("Query"): G.Op("&").Qual(BSON, "M").Values(G.Dict{ // G.Lit(relation.Attr + "._id"): G.Id("f").Dot("Id"), // }), // }), // G.Id(cIndex).Op("<-").Id("Models").Dot("Exist").Call(G.Id("filter")), // ).Call().Line()) // } // // Adiciona as variaveis de canal // b.Add(G.Var().DefsFunc(func(b2 *G.Group) { // // Gera o case para cada relacao // for _, v := range vars { // b2.Add(v) // } // })) // // Adiciona as chamadas das rotinas que consultam a existencia de dependencia // for _, r := range rotines { // // fmt.Printf("%#v", r) // b.Add(r) // } // // Geracao do for select // b.Add(G.For( // G.Id("i").Op(":=").Lit(0), // G.Id("i").Op("<").Lit(relationCount), // G.Id("i").Op("++"), // ).Block(G.Select().BlockFunc(func(b1 *G.Group) { // // Gera o case para cada relacao // for _, case1 := range cases { // b1.Add(case1) // } // })).Line()) // b.Return(G.False()) // // fmt.Printf("%#v") // }) // x.Add(block) // }).Line() // if { // createDepFunc = true // do.Add(G.If(G.Id(dependenceMethod).Call( // G.Id("filter"), // )).Block( // G.Id("err").Op("=").Qual(API_URL, "Error").Call( // G.Qual(API_URL, "ERR_CONFLICT"), // G.Lit(fmt.Sprintf("Ocorreu um conflito ao remover a entidade '%s'", method.Entity)), // ), // G.Return(), // ).Line()) // } // ctx.Statement.Block( // G.Id(`filter := ctx.Values.Get("$filter")`).Assert(G.Op("*").Qual(API_URL, "Filter")).Line(), // G.Id("filter").Dot("DB").Op("=").Lit(dbName), // G.Id("filter").Dot("Collection").Op("=").Lit(collectionName).Line(), // // Verifica se o tem tem dependencias // G.Do(func(do *G.Statement) { // if SR.Has(method.Entity) { // createDepFunc = true // do.Add(G.If(G.Id(dependenceMethod).Call( // G.Id("filter"), // )).Block( // G.Id("err").Op("=").Qual(API_URL, "Error").Call( // G.Qual(API_URL, "ERR_CONFLICT"), // G.Lit(fmt.Sprintf("Ocorreu um conflito ao remover a entidade '%s'", method.Entity)), // ), // G.Return(), // ).Line()) // } // // fmt.Println("GenerateFunc" + method.Entity + "|" + dependenceMethod) // }), // G.Do(func(s *G.Statement) { // if method.BeforePersistAction { // fnName := fmt.Sprintf("Before%s%s", strings.Title(method.ID), method.Entity) // s.Add(G.Id(fmt.Sprintf(` // // Chama uma função onde são descritas as ações executadas antes da entidade ser persistida. // if err = %s(ctx, resp); err != nil { // return // } // `, fnName))) // // part := s.Comment("").Line() // // part.If( // // G.List(G.Id("fn"), G.Id("err")).Op("=").Id(fnName).Call(G.Id("ctx"), G.Id("patchs")), // // G.Id("err").Op("!=").Id("nil"), // // ).Block(G.Return()) // } // }), // // Executa a remocao do item // // G.If( // // G.List(G.Id("_"), G.Id("err")).Op("=").Id("Models").Dot("RemoveOne").Call( // // G.Id("filter"), // // ), // G.Id(` // filter.Patchs = &`).Qual(BSON, "A").Id(`{ // bson.M{ // "$set": bson.M{ // "deleted": true, // "deletedIn": `).Qual("time", "Now").Id(`().Unix(), // }, // }, // }`), // generateHookCall(project, method, "beforePersist"), // G.Id(`if _, err = models.Api.PatchOne(filter), err !`), // G.Return(), // // G.Return(G.Nil()), // ). // -------------------------------------------------- // G.Id("err").Op("!=").Id("nil"), // ).Block( // G.Return(G.Id("err")), // G.Return(), // ), // G.Var().Defs( // G.Id("err").Op("*").Qual(API_ERROR, "Error"), // // G.Id("entity").Op("=").Op("&").Id(method.Entity).Values(), // ).Line(), // fmt.Println("Compont:" + method.Entity) // block.Add( // x.Var().Defs( // G.Id("err").Op("*").Qual(API_ERROR, "Error"), // G.Id("entity").Op("=").Op("&").Id(method.Entity).Values(), // ), // ) // vars.Defs(varList...)