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 }