func extractID(value interface{}) string { id := util.MaybeString(value) id = strings.Replace(id, " ", "", -1) id = strings.Replace(id, "{{", "", -1) id = strings.Replace(id, "}}", "", -1) return id }
func include(stmt *Stmt) (func(*Context) (interface{}, error), error) { source := util.MaybeString(stmt.RawData["include"]) if !filepath.IsAbs(source) { currentSource := stmt.File source = filepath.Clean(filepath.Join(filepath.Dir(currentSource), source)) } importedCode, err := LoadYAMLFile(source) if err != nil { return nil, stmt.Errorf("yaml parse error: %s", err) } stmt.Args = map[string]Value{} for key, value := range stmt.RawData { stmt.Args[key], err = NewValue(value) if err != nil { return nil, stmt.Errorf("yaml parse error: %s", err) } } stmt.File = source stmts, err := MakeStmts(stmt.File, importedCode) if err != nil { return nil, stmt.Errorf("import code parse error: %s", err) } stmt.Vars, err = MapToValue(util.MaybeMap(stmt.RawData["vars"])) if err != nil { return nil, stmt.Errorf("yaml parse error: %s", err) } return StmtsToFunc(stmt.funcName, stmts) }
// Extend clones context and extend it func (context *Context) Extend(values map[string]interface{}) *Context { newContext := NewContext(context.VM.Clone()) for key, value := range context.data { newContext.Set(key, value) } for key, value := range values { newContext.Set(util.MaybeString(key), value) } return newContext }
func command(stmt *gohanscript.Stmt) (func(*gohanscript.Context) (interface{}, error), error) { var err error stmt.Args, err = gohanscript.MapToValue(util.MaybeMap(stmt.RawData["args"])) if err != nil { return nil, err } stmt.Args["command"], err = gohanscript.NewValue(stmt.RawData["command"]) if err != nil { return nil, err } return func(context *gohanscript.Context) (interface{}, error) { chdir := stmt.Arg("chdir", context) if chdir != nil { currentDir, _ := filepath.Abs(".") os.Chdir(util.MaybeString(chdir)) defer os.Chdir(currentDir) } command := util.MaybeString(stmt.Arg("command", context)) parts := strings.Fields(command) result, err := exec.Command(parts[0], parts[1:]...).CombinedOutput() return string(result), err }, nil }
func transactionFunc(stmt *gohanscript.Stmt) (func(*gohanscript.Context) (interface{}, error), error) { stmts, err := gohanscript.MakeStmts(stmt.File, stmt.RawNode["transaction"]) if err != nil { return nil, err } runner, err := gohanscript.StmtsToFunc("transaction", stmts) if err != nil { return nil, err } return func(context *gohanscript.Context) (interface{}, error) { dbVar := util.MaybeString(stmt.RawData["db"]) if dbVar == "" { dbVar = "db" } rawDB, err := context.Get(dbVar) if err != nil { return nil, err } connection := rawDB.(db.DB) tx, err := connection.Begin() if err != nil { return nil, err } transactionVar := util.MaybeString(stmt.RawData["transaction_var"]) if transactionVar == "" { transactionVar = "transaction" } context.Set(transactionVar, tx) value, err := runner(context) if err == nil { tx.Commit() } tx.Close() return value, err }, nil }
func define(stmt *Stmt) (func(*Context) (interface{}, error), error) { var err error funcName := util.MaybeString(stmt.Args["name"].Value(nil)) defineNode := MappingNodeToMap(stmt.RawNode["define"]) funcArgs := util.MaybeMap(stmt.Args["args"].Value(nil)) stmts, err := MakeStmts(stmt.File, defineNode["body"]) if err != nil { return nil, stmt.Errorf("error in define body: %s", err) } var body func(*Context) (interface{}, error) RegisterStmtParser( funcName, func(aStmt *Stmt) (func(*Context) (interface{}, error), error) { for key := range funcArgs { _, ok := aStmt.Args[key] if !ok { return nil, fmt.Errorf("missing augument %s", key) } } return func(context *Context) (value interface{}, err error) { vm := context.VM newContext := NewContext(vm) for key := range funcArgs { newContext.Set(key, aStmt.Arg(key, context)) } value, err = body(newContext) if vm.debugReturn { vm.debugReturn = false vm.debug = true } return }, nil }) body, err = StmtsToFunc("funcName", stmts) if err != nil { return nil, err } return func(context *Context) (interface{}, error) { return nil, nil }, nil }
//NewSchemaFromObj is a constructor for a schema by obj func NewSchemaFromObj(rawTypeData interface{}) (*Schema, error) { typeData := rawTypeData.(map[string]interface{}) metaschema, ok := GetManager().Schema("schema") if ok { err := metaschema.Validate(metaschema.JSONSchema, typeData) if err != nil { return nil, err } } id := util.MaybeString(typeData["id"]) if id == "" { return nil, &typeAssertionError{"id"} } plural := util.MaybeString(typeData["plural"]) if plural == "" { return nil, &typeAssertionError{"plural"} } title := util.MaybeString(typeData["title"]) if title == "" { return nil, &typeAssertionError{"title"} } description := util.MaybeString(typeData["description"]) if description == "" { return nil, &typeAssertionError{"description"} } singular := util.MaybeString(typeData["singular"]) if singular == "" { return nil, &typeAssertionError{"singular"} } schema := NewSchema(id, plural, title, description, singular) schema.Prefix = util.MaybeString(typeData["prefix"]) schema.URL = util.MaybeString(typeData["url"]) schema.Type = util.MaybeString(typeData["type"]) schema.Parent = util.MaybeString(typeData["parent"]) schema.OnParentDeleteCascade, _ = typeData["on_parent_delete_cascade"].(bool) schema.NamespaceID = util.MaybeString(typeData["namespace"]) schema.IsolationLevel = util.MaybeMap(typeData["isolation_level"]) jsonSchema, ok := typeData["schema"].(map[string]interface{}) if !ok { return nil, &typeAssertionError{"schema"} } schema.JSONSchema = jsonSchema schema.Metadata = util.MaybeMap(typeData["metadata"]) schema.Extends = util.MaybeStringList(typeData["extends"]) actions := util.MaybeMap(typeData["actions"]) schema.Actions = []Action{} for actionID, actionBody := range actions { action, err := NewActionFromObject(actionID, actionBody) if err != nil { return nil, err } schema.Actions = append(schema.Actions, action) } if err := schema.Init(); err != nil { return nil, err } return schema, nil }
func httpServer(stmt *gohanscript.Stmt) (func(*gohanscript.Context) (interface{}, error), error) { return func(globalContext *gohanscript.Context) (interface{}, error) { m := martini.Classic() var mutex = &sync.Mutex{} history := []interface{}{} server := map[string]interface{}{ "history": history, } m.Handlers() m.Use(middleware.Logging()) m.Use(martini.Recovery()) rawBody := util.MaybeMap(stmt.RawData["http_server"]) paths := util.MaybeMap(rawBody["paths"]) middlewareCode := util.MaybeString(rawBody["middleware"]) if middlewareCode != "" { vm := gohanscript.NewVM() err := vm.LoadString(stmt.File, middlewareCode) if err != nil { return nil, err } m.Use(func(w http.ResponseWriter, r *http.Request) { context := globalContext.Extend(nil) fillInContext(context.Data(), r, w, nil) reqData, _ := ioutil.ReadAll(r.Body) buff := ioutil.NopCloser(bytes.NewBuffer(reqData)) r.Body = buff var data interface{} if reqData != nil { json.Unmarshal(reqData, &data) } context.Set("request", data) vm.Run(context.Data()) }) } m.Use(func(w http.ResponseWriter, r *http.Request) { reqData, _ := ioutil.ReadAll(r.Body) buff := ioutil.NopCloser(bytes.NewBuffer(reqData)) r.Body = buff var data interface{} if reqData != nil { json.Unmarshal(reqData, &data) } mutex.Lock() server["history"] = append(server["history"].([]interface{}), map[string]interface{}{ "method": r.Method, "path": r.URL.String(), "data": data, }) mutex.Unlock() }) for path, body := range paths { methods, ok := body.(map[string]interface{}) if !ok { continue } for method, rawRouteBody := range methods { routeBody, ok := rawRouteBody.(map[string]interface{}) if !ok { continue } code := util.MaybeString(routeBody["code"]) vm := gohanscript.NewVM() err := vm.LoadString(stmt.File, code) if err != nil { return nil, err } switch method { case "get": m.Get(path, func(w http.ResponseWriter, r *http.Request, p martini.Params) { context := globalContext.Extend(nil) fillInContext(context.Data(), r, w, p) vm.Run(context.Data()) serveResponse(w, context.Data()) }) case "post": m.Post(path, func(w http.ResponseWriter, r *http.Request, p martini.Params) { context := globalContext.Extend(nil) fillInContext(context.Data(), r, w, p) requestData, _ := middleware.ReadJSON(r) context.Set("request", requestData) vm.Run(context.Data()) serveResponse(w, context.Data()) }) case "put": m.Put(path, func(w http.ResponseWriter, r *http.Request, p martini.Params) { context := globalContext.Extend(nil) fillInContext(context.Data(), r, w, p) requestData, _ := middleware.ReadJSON(r) context.Set("request", requestData) vm.Run(context.Data()) serveResponse(w, context.Data()) }) case "delete": m.Delete(path, func(w http.ResponseWriter, r *http.Request, p martini.Params) { context := globalContext.Extend(nil) fillInContext(context.Data(), r, w, p) vm.Run(context.Data()) serveResponse(w, context.Data()) }) } } } testMode := stmt.Args["test"].Value(globalContext).(bool) if testMode { ts := httptest.NewServer(m) server["server"] = ts return server, nil } m.RunOnAddr(stmt.Args["address"].Value(globalContext).(string)) return nil, nil }, nil }
//NewStmt makes gohan statement from yaml node func NewStmt(FileName string, node *yaml.Node) (stmt *Stmt, err error) { if node == nil { return nil, nil } stmt = &Stmt{} stmt.RawNode = MappingNodeToMap(node) stmt.Line = node.Line + 1 stmt.Column = node.Column var rawData interface{} yaml.UnmarshalNode(node, &rawData) stmt.RawData = util.MaybeMap(convertMapformat(rawData)) stmt.Name = util.MaybeString(stmt.RawData["name"]) stmt.File, _ = filepath.Abs(FileName) stmt.Dir = filepath.Dir(stmt.File) stmt.Always, err = MakeStmts(FileName, stmt.RawNode["always"]) if err != nil { return nil, stmt.Error(err) } stmt.Rescue, err = MakeStmts(FileName, stmt.RawNode["rescue"]) if err != nil { return nil, stmt.Error(err) } stmt.ElseStmt, err = MakeStmts(FileName, stmt.RawNode["else"]) if err != nil { return nil, stmt.Error(err) } stmt.Retry = util.MaybeInt(stmt.RawData["retries"]) stmt.Worker = util.MaybeInt(stmt.RawData["worker"]) stmt.LoopVar = util.MaybeString(stmt.RawData["loop_var"]) if stmt.LoopVar == "" { stmt.LoopVar = "item" } if stmt.Retry == 0 { stmt.Retry = 1 } stmt.Delay = util.MaybeInt(stmt.RawData["delay"]) stmt.WithItems, err = NewValue(stmt.RawData["with_items"]) if err != nil { return nil, stmt.Error(err) } stmt.WithDict, err = NewValue(stmt.RawData["with_dict"]) if err != nil { return nil, stmt.Error(err) } if stmt.RawData["when"] != nil { stmt.When, err = CompileExpr(util.MaybeString(stmt.RawData["when"])) if err != nil { return nil, stmt.Error(err) } } if stmt.RawData["until"] != nil { stmt.Until, err = CompileExpr(util.MaybeString(stmt.RawData["until"])) if err != nil { return nil, stmt.Error(err) } } stmt.Register = util.MaybeString(stmt.RawData["register"]) stmt.Vars, err = MapToValue(util.MaybeMap(stmt.RawData["vars"])) if err != nil { return nil, stmt.Error(err) } return stmt, nil }
// MaybeString returns a string func (context *Context) MaybeString(key string) string { return util.MaybeString(context.MayGet(key)) }