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

     1  package modifyx
     2  
     3  import (
     4  	"gitee.com/zhongguo168a/gocodes/datax/convertx"
     5  	"strconv"
     6  )
     7  
     8  func (s *Object) RefClassName() string {
     9  	return s.source.className
    10  }
    11  
    12  // 新建一个对象
    13  func NewObject(src *Source) (obj *Object) {
    14  	obj = newObject()
    15  	obj.source = src
    16  	//
    17  	obj.sourceData = src.origin
    18  	obj.path = src.className
    19  	obj.initData()
    20  
    21  	return
    22  }
    23  
    24  func newObject() (obj *Object) {
    25  	obj = &Object{}
    26  	obj.ints = map[string]int{}
    27  	obj.uints = map[string]uint{}
    28  	obj.floats = map[string]float64{}
    29  	obj.strings = map[string]string{}
    30  	obj.bools = map[string]bool{}
    31  	obj.temps = map[string]interface{}{}
    32  	obj.runtime = map[string]interface{}{}
    33  	obj.disablePoolField = map[string]bool{}
    34  	return
    35  }
    36  
    37  // 修正对象
    38  // 如果需要在运行时,替换源的数据,可通过设置runtime实现
    39  type Object struct {
    40  	source *Source
    41  	// 字段的路径
    42  	path string
    43  	// 在父对象中的字段名字
    44  	field string
    45  	// 父数据
    46  	parent map[string]interface{}
    47  	// 缓存的map/array/struct等对象, 避免重复创建对象
    48  	temps map[string]interface{}
    49  	//
    50  	creators map[string]func(obj IObject) IObject
    51  	creator  func(obj IObject) IObject
    52  	// 当前修正对象指向的源数据
    53  	sourceData      map[string]interface{}
    54  	sourceDataArray []interface{}
    55  	// 运行时设置的数据
    56  	runtime map[string]interface{}
    57  	// 最终的数据, 采用不同类型的原因是,初始值
    58  	ints    map[string]int
    59  	uints   map[string]uint
    60  	floats  map[string]float64
    61  	strings map[string]string
    62  	bools   map[string]bool
    63  	// 需要使用修正池修正的字段
    64  	// 用于性能优化,避免进入修正池流程。
    65  	disablePoolField map[string]bool
    66  	//
    67  	disabelPool bool
    68  }
    69  
    70  func (s *Object) RefClassCreator(field string, creator func(object IObject) IObject) {
    71  	if s.creators == nil {
    72  		s.creators = map[string]func(obj IObject) IObject{}
    73  	}
    74  	s.creators[field] = creator
    75  }
    76  
    77  func (s *Object) initData() {
    78  	for key, val := range s.sourceData {
    79  		switch v := val.(type) {
    80  		//case int:
    81  		//	s.ints[key] = v
    82  		//case uint:
    83  		//	s.uints[key] = v
    84  		//case float64:
    85  		//	s.floats[key] = v
    86  		case bool:
    87  			s.bools[key] = v
    88  		case string:
    89  			s.strings[key] = v
    90  		}
    91  	}
    92  }
    93  
    94  func (s *Object) getOriginBool(field string) bool {
    95  	// 运行时
    96  	if rval, has := s.runtime[field]; has {
    97  		return rval.(bool)
    98  	}
    99  	return convertx.AnyToBool(s.sourceData[field])
   100  }
   101  
   102  func (s *Object) getOriginFloat(field string) float64 {
   103  	// 运行时
   104  	if rval, has := s.runtime[field]; has {
   105  		return rval.(float64)
   106  	}
   107  	return convertx.AnyToFloat64(s.sourceData[field])
   108  }
   109  func (s *Object) getOriginInt(field string) int {
   110  	// 运行时
   111  	if rval, has := s.runtime[field]; has {
   112  		return rval.(int)
   113  	}
   114  	return convertx.AnyToInt(s.sourceData[field])
   115  }
   116  
   117  func (s *Object) Dispose() {
   118  	s.sourceData = nil
   119  	s.runtime = nil
   120  	s.ints = nil
   121  	s.floats = nil
   122  	s.strings = nil
   123  	s.bools = nil
   124  	s.parent = nil
   125  	s.temps = nil
   126  	s.source = nil
   127  }
   128  
   129  // 修正后的整型
   130  func (s *Object) RefInt(field string) int {
   131  	origin := s.getOriginInt(field)
   132  	s.ints[field] = origin
   133  	// 池修正
   134  	if !s.disabelPool {
   135  		if !s.disablePoolField[field] {
   136  			pools := s.source.pools
   137  			if pools != nil {
   138  				lastkey := s.path + "/" + field
   139  				if pools.IsPropChanged(lastkey) {
   140  					// 更新属性
   141  					s.ints[field] = pools.GetNewPropInt(lastkey, origin)
   142  				}
   143  			}
   144  		}
   145  	}
   146  
   147  	return s.ints[field]
   148  
   149  }
   150  
   151  func (s *Object) resetBool(field string) {
   152  	// 运行时
   153  	if rval, has := s.runtime[field]; has {
   154  		s.bools[field] = rval.(bool)
   155  	} else {
   156  		// 使用源数据进行初始化B
   157  		s.bools[field] = convertx.AnyToBool(s.sourceData[field])
   158  	}
   159  	return
   160  }
   161  
   162  // 修正后的整型
   163  func (s *Object) RefBool(field string) bool {
   164  	origin := s.getOriginBool(field)
   165  	s.bools[field] = origin
   166  	// 池修正
   167  	if !s.disabelPool {
   168  		if !s.disablePoolField[field] {
   169  			pools := s.source.pools
   170  			if pools != nil {
   171  				lastkey := s.path + "/" + field
   172  				if pools.IsPropChanged(lastkey) {
   173  					// 更新属性
   174  					s.bools[field] = pools.GetNewPropBool(lastkey, origin)
   175  				}
   176  			}
   177  		}
   178  	}
   179  
   180  	return s.bools[field]
   181  }
   182  
   183  // 修正后的浮点型
   184  func (s *Object) RefFloat64(field string) float64 {
   185  	origin := s.getOriginFloat(field)
   186  	s.floats[field] = origin
   187  	// 池修正
   188  	if !s.disabelPool {
   189  		if !s.disablePoolField[field] {
   190  			pools := s.source.pools
   191  			if pools != nil {
   192  				lastkey := s.path + "/" + field
   193  				if pools.IsPropChanged(lastkey) {
   194  					// 更新属性
   195  					s.floats[field] = pools.GetNewPropFloat(lastkey, origin)
   196  				}
   197  			}
   198  		}
   199  	}
   200  
   201  	return s.floats[field]
   202  
   203  }
   204  
   205  // RefSourceData 获取原始数据
   206  // 可通过 mapx.Int(origin, fieldName)获取指定内容的值
   207  func (s *Object) RefSourceData() (origin map[string]interface{}) {
   208  	return s.sourceData
   209  }
   210  
   211  // RefSource 获取原始数据指定的字段
   212  func (s *Object) RefSource(field string) interface{} {
   213  	return s.sourceData[field]
   214  }
   215  
   216  func (s *Object) RefUint(field string) (val uint) {
   217  	return uint(s.RefInt(field))
   218  }
   219  
   220  func (s *Object) resetString(field string) {
   221  	// 运行时
   222  	if rval, has := s.runtime[field]; has {
   223  		s.strings[field] = rval.(string)
   224  	} else {
   225  		// 使用源数据进行初始化B
   226  		s.strings[field] = convertx.AnyToString(s.sourceData[field])
   227  	}
   228  	return
   229  }
   230  
   231  func (s *Object) RefString(field string) (val string) {
   232  	// 池修正
   233  	//if !s.disabelPool {
   234  	//	if !s.disablePoolField[field] {
   235  	//		root := s.source.root
   236  	//		versions := s.source.versions
   237  	//		if root != nil {
   238  	//			lastkey := s.path + "/" + field
   239  	//			pool := root.GetPool()
   240  	//			if pool.IsPropChanged(lastkey, versions[lastkey]) {
   241  	//				// 更新属性
   242  	//				s.resetString(field)
   243  	//				s.strings[field], versions[lastkey] = pool.GetNewPropString(root, lastkey, s.strings[field])
   244  	//			}
   245  	//		}
   246  	//
   247  	//	}
   248  	//}
   249  
   250  	return s.strings[field]
   251  }
   252  
   253  func (s *Object) RefArray(field string) (r IArray) {
   254  	iobj, hastemp := s.temps[field]
   255  	if hastemp == false {
   256  		obj := newArray()
   257  		obj.source = s.source
   258  		obj.parent = s.sourceData
   259  		obj.field = field
   260  		obj.path = s.path + "/" + field
   261  		obj.creator = s.creators[field]
   262  		//
   263  		m, has := s.sourceData[field]
   264  		if has == true && m != nil {
   265  			switch mval := m.(type) {
   266  			case []interface{}:
   267  				obj.sourceData = mval
   268  			case map[string]interface{}:
   269  				max := func() (x int) {
   270  					for key := range mval {
   271  						index, _ := strconv.Atoi(key)
   272  						if index > x {
   273  							x = index
   274  						}
   275  					}
   276  					return
   277  				}()
   278  				obj.sourceData = make([]interface{}, max, max)
   279  				for key, val := range mval {
   280  					index, _ := strconv.Atoi(key)
   281  					obj.sourceData[index] = val
   282  				}
   283  			}
   284  
   285  			obj.initData()
   286  		}
   287  		iobj = obj
   288  		s.temps[field] = iobj
   289  	}
   290  
   291  	r = iobj.(IArray)
   292  	return
   293  }
   294  
   295  func (s *Object) RefMap(field string) (r IObject) {
   296  	iobj, hastemp := s.temps[field]
   297  	if hastemp == false {
   298  		obj := newObject()
   299  		obj.source = s.source
   300  		obj.parent = s.sourceData
   301  		obj.field = field
   302  		obj.path = s.path + "/" + field
   303  		obj.temps = map[string]interface{}{}
   304  		//
   305  		m, has := s.sourceData[field]
   306  		if has == true && m != nil {
   307  			obj.sourceData = m.(map[string]interface{})
   308  			obj.initData()
   309  		}
   310  
   311  		creator, hascreator := s.creators[field]
   312  		if hascreator {
   313  			obj.creator = creator
   314  		}
   315  		iobj = obj
   316  		s.temps[field] = iobj
   317  	}
   318  
   319  	r = iobj.(IObject)
   320  	return
   321  }
   322  
   323  func (s *Object) RefObject(field string) (r IObject) {
   324  	iobj, hastemp := s.temps[field]
   325  	if hastemp == false {
   326  		obj := newObject()
   327  		obj.source = s.source
   328  		obj.parent = s.sourceData
   329  		obj.field = field
   330  		obj.path = s.path + "/" + field
   331  		obj.temps = map[string]interface{}{}
   332  		//
   333  		m, has := s.sourceData[field]
   334  		if has == true && m != nil {
   335  			obj.sourceData = m.(map[string]interface{})
   336  			obj.initData()
   337  		}
   338  
   339  		if s.creator != nil { // 只有map对象会有此属性
   340  			iobj = s.creator(obj)
   341  		} else {
   342  			//
   343  			creator, hascreator := s.creators[field]
   344  			if !hascreator {
   345  				iobj = obj
   346  			} else {
   347  				iobj = creator(obj)
   348  			}
   349  
   350  		}
   351  
   352  		s.temps[field] = iobj
   353  	}
   354  
   355  	r = iobj.(IObject)
   356  	return
   357  }
   358  
   359  // SetRuntimeFloat 运行时修改的数据, 用于直接替换掉origin数据, 再进行池修正
   360  // 用于已知目标的情况下使用, 可提高运行效率, 例如初始化时, 为目标单位赋予初值
   361  // 注: 需要注意设置的类型
   362  func (s *Object) SetRuntimeFloat(field string, val float64) {
   363  	s.runtime[field] = val
   364  	s.floats[field] = val
   365  }
   366  func (s *Object) SetRuntimeInt(field string, val int) {
   367  	s.runtime[field] = val
   368  	s.ints[field] = val
   369  }
   370  func (s *Object) SetRuntimeBool(field string, val bool) {
   371  	s.runtime[field] = val
   372  	s.bools[field] = val
   373  }
   374  func (s *Object) SetRuntimeString(field string, val string) {
   375  	s.runtime[field] = val
   376  	s.strings[field] = val
   377  }
   378  
   379  func (s *Object) RefIsNil() bool {
   380  	return s.sourceData == nil
   381  }
   382  
   383  func (s *Object) RefLength() int {
   384  	return len(s.sourceData)
   385  }
   386  
   387  func (s *Object) RefKeys() (r []string) {
   388  	if s.RefIsNil() {
   389  		return
   390  	}
   391  
   392  	for key := range s.sourceData {
   393  		r = append(r, key)
   394  	}
   395  	return
   396  }
   397  
   398  // 只用于无修正场合
   399  func (s *Object) MapKeyOf(conf func(item interface{}) bool) string {
   400  	if s.RefIsNil() {
   401  		return ""
   402  	}
   403  
   404  	for key := range s.sourceData {
   405  		if conf(s.sourceData[key]) {
   406  			return key
   407  		}
   408  	}
   409  
   410  	return ""
   411  }
   412  
   413  func (s *Object) GetMapFloat() (r map[string]float64) {
   414  	iobj, hastemp := s.temps["mapfloat"]
   415  	if hastemp == false {
   416  		r = map[string]float64{}
   417  		iobj = r
   418  		s.temps["mapfloat"] = r
   419  	}
   420  	r = iobj.(map[string]float64)
   421  	for key := range s.sourceData {
   422  		r[key] = s.RefFloat64(key)
   423  	}
   424  	return
   425  }
   426  
   427  func (s *Object) GetMapFloatModify() (r map[string]float64) {
   428  	iobj, hastemp := s.temps["mapfloatmod"]
   429  	if hastemp == false {
   430  		r = map[string]float64{}
   431  		iobj = r
   432  		s.temps["mapfloatmod"] = r
   433  	}
   434  	r = iobj.(map[string]float64)
   435  	for key := range s.sourceData {
   436  		r[key] = s.RefFloat64(key)
   437  	}
   438  	return
   439  }
   440  
   441  // 只用于无修正场合
   442  func (s *Object) ToMapString() (r map[string]string) {
   443  	iobj, hastemp := s.temps["mapstring"]
   444  	if hastemp == false {
   445  		r = map[string]string{}
   446  		for key := range s.sourceData {
   447  			r[key] = s.sourceData[key].(string)
   448  		}
   449  		iobj = r
   450  		s.temps["mapstring"] = r
   451  	}
   452  	r = iobj.(map[string]string)
   453  	return
   454  }
   455  
   456  // 只用于无修正场合
   457  func (s *Object) ToArrayString() (r []string) {
   458  	iobj, hastemp := s.temps["arraystring"]
   459  	if hastemp == false {
   460  		r = make([]string, s.RefLength())
   461  		for key, val := range s.sourceData {
   462  			idx := convertx.AnyToInt64(key)
   463  			r[idx] = val.(string)
   464  		}
   465  		iobj = r
   466  		s.temps["arraystring"] = r
   467  	}
   468  	r = iobj.([]string)
   469  	return
   470  }
   471  
   472  // 只用于无修正场合
   473  func (s *Object) GetArrayFloatModify() (r []float64) {
   474  	iobj, hastemp := s.temps["arrayfloat64mod"]
   475  	if hastemp == false {
   476  		r = make([]float64, s.RefLength())
   477  		iobj = r
   478  		s.temps["arrayfloat64mod"] = r
   479  	}
   480  	for key := range s.sourceData {
   481  		idx := convertx.AnyToInt64(key)
   482  		r[idx] = s.RefFloat64(key)
   483  	}
   484  	r = iobj.([]float64)
   485  	return
   486  }