gitee.com/zhongguo168a/gocodes@v0.0.0-20230609140523-e1828349603f/datax/versionx/cachez-object.go (about)

     1  package versionx
     2  
     3  import (
     4  	"gitee.com/zhongguo168a/gocodes/datax"
     5  	"gitee.com/zhongguo168a/gocodes/datax/convertx"
     6  	"gitee.com/zhongguo168a/gocodes/datax/floatx"
     7  	"gitee.com/zhongguo168a/gocodes/datax/mapx"
     8  )
     9  
    10  // 独立用
    11  func NewObject() (obj *Object) {
    12  	obj = &Object{}
    13  	obj.Source = NewSource()
    14  	obj.data = obj.Source.origin
    15  	obj.versionPaths = append(obj.versionPaths, "")
    16  	obj.temps = datax.M{}
    17  	return obj
    18  }
    19  
    20  type Object struct {
    21  	*Source
    22  	// 当前管理的数据
    23  	data datax.M
    24  	// 字段的路径
    25  	path string
    26  	// 在父对象中的字段名字
    27  	field string
    28  	// 父数据
    29  	parent datax.M
    30  	// 父对象的路径集合
    31  	versionPaths []string
    32  	// 缓存的map/array/struct等对象, 避免重复创建对象
    33  	temps datax.M
    34  	//
    35  	creators map[string]func(obj IObject) IObject
    36  	creator  func(obj IObject) IObject
    37  }
    38  
    39  // 字段的路径
    40  func (s *Object) RefFieldPath() string {
    41  	return s.path
    42  }
    43  
    44  // 实例是否发生变化
    45  func (s *Object) RefFieldChanged() bool {
    46  	return s.versions[s.path] > s.lastVersion
    47  }
    48  func (s *Object) RefArray(field string) datax.A {
    49  	val, has := s.data[field]
    50  	if has == false {
    51  		val = make(datax.A, 0, 0)
    52  		s.data[field] = val
    53  	}
    54  	return val.(datax.A)
    55  }
    56  
    57  func (s *Object) RefData() datax.M {
    58  	return s.data
    59  }
    60  
    61  func (s *Object) RefGet(field string) (val interface{}) {
    62  	return s.data[field]
    63  }
    64  
    65  func (s *Object) RefHas(field string) bool {
    66  	_, has := s.data[field]
    67  	return has
    68  }
    69  
    70  func (s *Object) RefUint(field string) uint {
    71  	return uint(s.RefInt(field))
    72  }
    73  
    74  func (s *Object) RefInt(field string) int {
    75  	val, has := s.data[field]
    76  	if has == false {
    77  		val = int(convertx.AnyToInt64(val))
    78  		s.data[field] = val
    79  	}
    80  	return val.(int)
    81  }
    82  
    83  func (s *Object) RefBool(field string) bool {
    84  	val, has := s.data[field]
    85  	if has == false {
    86  		val = convertx.AnyToBool(val)
    87  		s.data[field] = val
    88  	}
    89  	return val.(bool)
    90  }
    91  
    92  func (s *Object) RefFloat64(field string) float64 {
    93  	val, has := s.data[field]
    94  	if has == false {
    95  		val = convertx.AnyToFloat64(val)
    96  		s.data[field] = val
    97  	}
    98  	return val.(float64)
    99  }
   100  func (s *Object) RefString(field string) string {
   101  	val, has := s.data[field]
   102  	if has == false {
   103  		val = convertx.AnyToString(val)
   104  		s.data[field] = val
   105  	}
   106  	return val.(string)
   107  }
   108  
   109  func (s *Object) RefMap(field string) (r IObject) {
   110  	iobj, hastemp := s.temps[field]
   111  	if hastemp == false {
   112  		obj := &Object{}
   113  		obj.Source = s.Source
   114  		obj.parent = s.data
   115  		obj.field = field
   116  		obj.path = s.path + "/" + field
   117  		obj.versionPaths = append(s.versionPaths, obj.path)
   118  		obj.temps = datax.M{}
   119  		//
   120  		m, has := s.data[field]
   121  		if has {
   122  			obj.data = m.(datax.M)
   123  		}
   124  
   125  		creator, hascreator := s.creators[field]
   126  		if hascreator {
   127  			obj.creator = creator
   128  		}
   129  		iobj = obj
   130  		s.temps[field] = obj
   131  	}
   132  	r = iobj.(IObject)
   133  	return
   134  }
   135  
   136  func (s *Object) RefClass(field string) IObject {
   137  	iobj, hastemp := s.temps[field]
   138  	if hastemp == false {
   139  		obj := &Object{}
   140  		obj.Source = s.Source
   141  		obj.parent = s.data
   142  		obj.field = field
   143  		obj.path = s.path + "/" + field
   144  		obj.versionPaths = append(s.versionPaths, obj.path)
   145  		obj.temps = datax.M{}
   146  		//
   147  		m, has := s.data[field]
   148  		if has {
   149  			obj.data = m.(datax.M)
   150  		}
   151  
   152  		if s.creator != nil { // 只有map对象会有此属性
   153  			iobj = s.creator(obj)
   154  		} else {
   155  			//
   156  			creator, hascreator := s.creators[field]
   157  			if hascreator {
   158  				iobj = creator(obj)
   159  			} else {
   160  				iobj = obj
   161  			}
   162  		}
   163  
   164  		s.temps[field] = iobj
   165  	}
   166  
   167  	return iobj.(IObject)
   168  }
   169  
   170  func (s *Object) RefClassCreator(field string, creator func(object IObject) IObject) {
   171  	if s.creators == nil {
   172  		s.creators = map[string]func(obj IObject) IObject{}
   173  	}
   174  	s.creators[field] = creator
   175  }
   176  
   177  // 0-无法比较 1-浮点数比较 2-其他比较
   178  func (s *Object) compareKind(val interface{}) int {
   179  	switch val.(type) {
   180  	case int:
   181  		return 2
   182  	case int8:
   183  		return 2
   184  	case int16:
   185  		return 2
   186  	case int32:
   187  		return 2
   188  	case int64:
   189  		return 2
   190  	case uint:
   191  		return 2
   192  	case uint8:
   193  		return 2
   194  	case uint16:
   195  		return 2
   196  	case uint32:
   197  		return 2
   198  	case uint64:
   199  		return 2
   200  	case float32:
   201  		return 1
   202  	case float64:
   203  		return 1
   204  	case string:
   205  		return 2
   206  	case bool:
   207  		return 2
   208  	}
   209  
   210  	return 0
   211  }
   212  
   213  // 只能设置基本类型
   214  func (s *Object) RefSet(field string, val interface{}) {
   215  	if s.data == nil {
   216  		panic("RefSet: data is nil")
   217  	}
   218  
   219  	switch s.compareKind(val) {
   220  	case 1:
   221  		a := s.RefFloat64(field)
   222  		if floatx.Eq(a, val.(float64)) {
   223  			return
   224  		}
   225  	case 2:
   226  		old := s.data[field]
   227  		if old == val { // 没有变化
   228  			return
   229  		}
   230  	}
   231  
   232  	s.data[field] = val
   233  	if s.enableVersion {
   234  		s.KeyVersionNew(s.versionPaths, s.path+"/"+field)
   235  	}
   236  
   237  	if s.onChange != nil {
   238  		s.onChange(s.path, field, val)
   239  	}
   240  	return
   241  }
   242  
   243  // 设置成nil
   244  func (s *Object) RefSetNil() {
   245  	s.parent[s.field] = nil
   246  	s.data = nil
   247  	s.temps = nil
   248  
   249  	// 不能删除,因为如果删除了,就没法同步删除map的场景
   250  	//delete(s.parent, s.field)
   251  	if s.enableVersion {
   252  		s.KeyVersionNew(s.versionPaths, s.path)
   253  	}
   254  
   255  	if s.onChange != nil {
   256  		s.onChange(s.path, s.field, nil)
   257  	}
   258  }
   259  
   260  // 新建结构, 旧的数据清除
   261  // 返回自身,便于链式调用
   262  func (s *Object) RefNew() IObject {
   263  	m := datax.M{}
   264  	s.parent[s.field] = m
   265  	s.data = m
   266  	s.temps = datax.M{}
   267  	if s.enableVersion {
   268  		s.KeyVersionNew(s.versionPaths, s.path)
   269  	}
   270  	return s
   271  }
   272  
   273  // 如果是空的才新建结构
   274  // 返回自身,便于链式调用
   275  func (s *Object) RefNewIfNil() IObject {
   276  	if s.data == nil {
   277  		return s.RefNew()
   278  	}
   279  	return s
   280  }
   281  
   282  func (s *Object) RefIsNil() bool {
   283  	return s.data == nil
   284  }
   285  
   286  func (s *Object) RefLength() int {
   287  	return len(s.data)
   288  }
   289  
   290  func (s *Object) RefKeys() (r []string) {
   291  	if s.RefIsNil() {
   292  		return
   293  	}
   294  	for key := range s.data {
   295  		r = append(r, key)
   296  	}
   297  	return
   298  }
   299  
   300  func (s *Object) RefReset(data map[string]interface{}) {
   301  	if s.RefIsNil() {
   302  		return
   303  	}
   304  	s.RefNew()
   305  	for key, val := range data {
   306  		s.RefSet(key, val)
   307  	}
   308  	return
   309  }
   310  
   311  func (s *Object) RefUpdate(data map[string]interface{}) {
   312  	if data == nil {
   313  		s.RefSetNil()
   314  		return
   315  	}
   316  	s.RefNewIfNil()
   317  	dataObject := s.data
   318  	temps := s.temps
   319  	for key, val := range data {
   320  		if val == nil {
   321  			temps[key] = nil
   322  			dataObject[key] = nil
   323  		} else {
   324  			switch v := val.(type) {
   325  			case map[string]interface{}:
   326  				tempVal, has := s.temps[key]
   327  				if has {
   328  					if tempVal != nil {
   329  						tempVal.(IObject).RefUpdate(v)
   330  					} else {
   331  						dataObject[key] = v
   332  					}
   333  				} else {
   334  					dataVal := dataObject[key]
   335  					if dataVal == nil {
   336  						dataVal = map[string]interface{}{}
   337  						dataObject[key] = dataVal
   338  					}
   339  					mapx.Copy(v, dataVal.(map[string]interface{}))
   340  				}
   341  			default:
   342  				s.RefSet(key, val)
   343  			}
   344  		}
   345  
   346  	}
   347  	return
   348  }