github.com/team-ide/go-dialect@v1.9.20/dialect/statement_context.go (about) 1 package dialect 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "reflect" 8 "sync" 9 ) 10 11 func NewStatementContext() (res *StatementContext) { 12 res = &StatementContext{ 13 dataCache: make(map[string]interface{}), 14 methodCache: make(map[string]*MethodInfo), 15 } 16 return 17 } 18 19 type MethodInfo struct { 20 name string 21 method reflect.Value 22 methodType reflect.Type 23 ins []reflect.Type 24 outs []reflect.Type 25 outErrorIndex *int 26 } 27 28 func (this_ *MethodInfo) Call(inValues []interface{}) (outValues []interface{}, err error) { 29 if len(inValues) != len(this_.ins) { 30 err = errors.New(fmt.Sprintf("func [%s] ins len is [%d] by inValues len is [%d]", this_.name, len(this_.ins), len(inValues))) 31 return 32 } 33 var callValues []reflect.Value 34 for i, inValue := range inValues { 35 in := this_.ins[i] 36 inValueType := reflect.TypeOf(inValue) 37 if in.Kind() != inValueType.Kind() { 38 // TODO 39 40 } 41 callValue := reflect.ValueOf(inValue) 42 callValues = append(callValues, callValue) 43 } 44 45 callResults := this_.method.Call(callValues) 46 for i, callResult := range callResults { 47 data := callResult.Interface() 48 outValues = append(outValues, data) 49 if this_.outErrorIndex != nil && *this_.outErrorIndex == i { 50 dataErr, ok := data.(error) 51 if ok { 52 err = dataErr 53 } 54 } 55 } 56 57 return 58 } 59 60 type StatementContext struct { 61 dataCache map[string]interface{} 62 dataCacheLock sync.Mutex 63 methodCache map[string]*MethodInfo 64 methodCacheLock sync.Mutex 65 } 66 67 func (this_ *StatementContext) GetData(name string) (value interface{}, find bool) { 68 this_.dataCacheLock.Lock() 69 defer this_.dataCacheLock.Unlock() 70 71 value, find = this_.dataCache[name] 72 //fmt.Println("GetData name:", name, ",value:", value) 73 return 74 } 75 76 func (this_ *StatementContext) SetData(name string, value interface{}) *StatementContext { 77 this_.dataCacheLock.Lock() 78 defer this_.dataCacheLock.Unlock() 79 80 this_.dataCache[name] = value 81 return this_ 82 } 83 84 func (this_ *StatementContext) SetJSONData(data interface{}) (err error) { 85 if data == nil { 86 return 87 } 88 bs, err := json.Marshal(data) 89 if err != nil { 90 return 91 } 92 if len(bs) == 0 { 93 return 94 } 95 dataMap := map[string]interface{}{} 96 err = json.Unmarshal(bs, &dataMap) 97 if err != nil { 98 return 99 } 100 this_.SetMapData(dataMap) 101 return 102 } 103 104 func (this_ *StatementContext) SetMapData(data map[string]interface{}) *StatementContext { 105 if data == nil { 106 return this_ 107 } 108 this_.dataCacheLock.Lock() 109 defer this_.dataCacheLock.Unlock() 110 111 for name, value := range data { 112 this_.dataCache[name] = value 113 } 114 115 return this_ 116 } 117 118 func (this_ *StatementContext) SetDataIfAbsent(name string, value interface{}) *StatementContext { 119 this_.dataCacheLock.Lock() 120 defer this_.dataCacheLock.Unlock() 121 122 if this_.dataCache[name] == nil { 123 this_.dataCache[name] = value 124 } 125 return this_ 126 } 127 128 func (this_ *StatementContext) GetMethod(name string) (method *MethodInfo, find bool) { 129 this_.methodCacheLock.Lock() 130 defer this_.methodCacheLock.Unlock() 131 132 method, find = this_.methodCache[name] 133 return 134 } 135 136 func (this_ *StatementContext) setMethod(name string, method *MethodInfo) *StatementContext { 137 this_.methodCacheLock.Lock() 138 defer this_.methodCacheLock.Unlock() 139 140 this_.methodCache[name] = method 141 return this_ 142 } 143 144 func (this_ *StatementContext) AddMethod(name string, methodFunc interface{}) *StatementContext { 145 method := reflect.ValueOf(methodFunc) 146 info := &MethodInfo{ 147 name: name, 148 method: method, 149 methodType: method.Type(), 150 } 151 for i := 0; i < info.methodType.NumIn(); i++ { 152 info.ins = append(info.ins, info.methodType.In(i)) 153 } 154 for i := 0; i < info.methodType.NumOut(); i++ { 155 out := info.methodType.Out(i) 156 switch out.String() { 157 case "error": 158 var i_ = new(int) 159 *i_ = i 160 info.outErrorIndex = i_ 161 break 162 } 163 info.outs = append(info.outs, out) 164 } 165 this_.setMethod(name, info) 166 return this_ 167 }