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  }