gitlab.com/evatix-go/core@v1.3.55/coredata/coredynamic/Dynamic.go (about)

     1  package coredynamic
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"reflect"
     7  	"strconv"
     8  
     9  	"gitlab.com/evatix-go/core/constants"
    10  	"gitlab.com/evatix-go/core/constants/bitsize"
    11  	"gitlab.com/evatix-go/core/coredata/corejson"
    12  	"gitlab.com/evatix-go/core/coredata/coreonce"
    13  	"gitlab.com/evatix-go/core/defaulterr"
    14  	"gitlab.com/evatix-go/core/errcore"
    15  	"gitlab.com/evatix-go/core/internal/messages"
    16  	"gitlab.com/evatix-go/core/internal/reflectinternal"
    17  	"gitlab.com/evatix-go/core/internal/strutilinternal"
    18  	"gitlab.com/evatix-go/core/issetter"
    19  )
    20  
    21  type Dynamic struct {
    22  	innerData       interface{}
    23  	isValid         bool
    24  	reflectType     reflect.Type
    25  	reflectVal      *reflect.Value
    26  	innerDataString *string
    27  	typeName        coreonce.StringOnce
    28  	length          coreonce.IntegerOnce
    29  	isPointer       issetter.Value
    30  }
    31  
    32  func InvalidDynamic() Dynamic {
    33  	return *InvalidDynamicPtr()
    34  }
    35  
    36  func InvalidDynamicPtr() *Dynamic {
    37  	return NewDynamicPtr(
    38  		nil,
    39  		false)
    40  }
    41  
    42  func NewDynamicValid(
    43  	data interface{},
    44  ) Dynamic {
    45  	return *NewDynamicPtr(data, true)
    46  }
    47  
    48  func NewDynamic(
    49  	data interface{},
    50  	isValid bool,
    51  ) Dynamic {
    52  	return *NewDynamicPtr(data, isValid)
    53  }
    54  
    55  func NewDynamicPtr(
    56  	data interface{},
    57  	isValid bool,
    58  ) *Dynamic {
    59  	return &Dynamic{
    60  		innerData: data,
    61  		isValid:   isValid,
    62  		typeName: coreonce.NewStringOnce(func() string {
    63  			return fmt.Sprintf(constants.SprintTypeFormat, data)
    64  		}),
    65  		length: coreonce.NewIntegerOnce(func() int {
    66  			if data == nil {
    67  				return 0
    68  			}
    69  
    70  			return LengthOfReflect(reflect.ValueOf(data))
    71  		}),
    72  	}
    73  }
    74  
    75  func (it *Dynamic) Data() interface{} {
    76  	return it.innerData
    77  }
    78  
    79  func (it *Dynamic) Value() interface{} {
    80  	return it.innerData
    81  }
    82  
    83  // Length Returns length of a slice, map, array
    84  //
    85  // It will also reduce from pointer
    86  //
    87  // Reference : https://cutt.ly/PnaWAFn | https://cutt.ly/jnaEig8 | https://play.golang.org/p/UCORoShXlv1
    88  func (it *Dynamic) Length() int {
    89  	return it.length.Value()
    90  }
    91  
    92  func (it *Dynamic) StructStringPtr() *string {
    93  	if it.innerDataString != nil {
    94  		return it.innerDataString
    95  	}
    96  
    97  	toString := strutilinternal.AnyToString(it.innerData)
    98  	it.innerDataString = &toString
    99  
   100  	return it.innerDataString
   101  }
   102  
   103  func (it *Dynamic) ReflectValue() *reflect.Value {
   104  	if it.reflectVal != nil {
   105  		return it.reflectVal
   106  	}
   107  
   108  	reflectValueOfAny := reflect.ValueOf(it.innerData)
   109  	it.reflectVal = &reflectValueOfAny
   110  
   111  	return it.reflectVal
   112  }
   113  
   114  func (it *Dynamic) MapToKeyVal() (*KeyValCollection, error) {
   115  	return MapAsKeyValSlice(*it.ReflectValue())
   116  }
   117  
   118  func (it *Dynamic) ReflectKind() reflect.Kind {
   119  	return it.ReflectValue().Kind()
   120  }
   121  
   122  func (it *Dynamic) ReflectTypeName() string {
   123  	return it.typeName.Value()
   124  }
   125  
   126  func (it *Dynamic) ReflectType() reflect.Type {
   127  	if it.reflectType != nil {
   128  		return it.reflectType
   129  	}
   130  
   131  	reflectType := reflect.TypeOf(it.innerData)
   132  	it.reflectType = reflectType
   133  
   134  	return it.reflectType
   135  }
   136  
   137  func (it *Dynamic) IsReflectTypeOf(
   138  	typeRequest reflect.Type,
   139  ) bool {
   140  	return it.ReflectType() == typeRequest
   141  }
   142  
   143  func (it *Dynamic) ItemReflectValueUsingIndex(index int) reflect.Value {
   144  	return it.ReflectValue().Index(index)
   145  }
   146  
   147  func (it *Dynamic) ItemReflectValueUsingKey(key interface{}) reflect.Value {
   148  	return it.ReflectValue().MapIndex(reflect.ValueOf(key))
   149  }
   150  
   151  func (it *Dynamic) ItemUsingIndex(index int) interface{} {
   152  	return it.ReflectValue().Index(index).Interface()
   153  }
   154  
   155  func (it *Dynamic) ItemUsingKey(key interface{}) interface{} {
   156  	return it.ReflectValue().MapIndex(reflect.ValueOf(key)).Interface()
   157  }
   158  
   159  func (it *Dynamic) String() string {
   160  	return *it.StructStringPtr()
   161  }
   162  
   163  func (it *Dynamic) StructString() string {
   164  	return *it.StructStringPtr()
   165  }
   166  
   167  func (it *Dynamic) IsReflectKind(checkingKind reflect.Kind) bool {
   168  	return it.ReflectKind() == checkingKind
   169  }
   170  
   171  func (it *Dynamic) IsPointer() bool {
   172  	if it.isPointer.IsUninitialized() {
   173  		it.isPointer = issetter.GetBool(
   174  			it.IsReflectKind(reflect.Ptr))
   175  	}
   176  
   177  	return it.isPointer.IsTrue()
   178  }
   179  
   180  func (it *Dynamic) IsValueType() bool {
   181  	return !it.IsPointer()
   182  }
   183  
   184  func (it *Dynamic) IsStructStringNullOrEmpty() bool {
   185  	return it.IsNull() || strutilinternal.IsNullOrEmpty(
   186  		it.StructStringPtr())
   187  }
   188  
   189  func (it *Dynamic) IsStructStringNullOrEmptyOrWhitespace() bool {
   190  	return it.IsNull() || strutilinternal.IsNullOrEmptyOrWhitespace(
   191  		it.StructStringPtr())
   192  }
   193  
   194  func (it *Dynamic) IsPrimitive() bool {
   195  	return reflectinternal.IsPrimitive(it.ReflectKind())
   196  }
   197  
   198  // IsNumber true if float (any), byte, int (any), uint(any)
   199  func (it *Dynamic) IsNumber() bool {
   200  	return reflectinternal.IsNumber(it.ReflectKind())
   201  }
   202  
   203  func (it *Dynamic) IntDefault(defaultInt int) (val int, isSuccess bool) {
   204  	if it.IsNull() {
   205  		return defaultInt, false
   206  	}
   207  
   208  	stringVal := it.StructString()
   209  	toInt, err := strconv.Atoi(stringVal)
   210  
   211  	if err == nil {
   212  		return toInt, true
   213  	}
   214  
   215  	return defaultInt, false
   216  }
   217  
   218  func (it *Dynamic) Float64() (val float64, err error) {
   219  	if it.IsNull() {
   220  		return constants.Zero, errcore.
   221  			ParsingFailedType.Error(
   222  			messages.DynamicFailedToParseToFloat64BecauseNull,
   223  			it.String())
   224  	}
   225  
   226  	stringVal := it.StructString()
   227  	valFloat, err2 := strconv.ParseFloat(stringVal, bitsize.Of64)
   228  
   229  	if err2 != nil {
   230  		reference := stringVal +
   231  			constants.NewLineUnix +
   232  			err2.Error()
   233  
   234  		return constants.Zero, errcore.
   235  			ParsingFailedType.Error(
   236  			errcore.FailedToConvertType.String(),
   237  			reference)
   238  	}
   239  
   240  	return valFloat, err
   241  }
   242  
   243  func (it *Dynamic) IsStruct() bool {
   244  	return it.ReflectKind() == reflect.Struct
   245  }
   246  
   247  func (it *Dynamic) IsFunc() bool {
   248  	return it.ReflectKind() == reflect.Func
   249  }
   250  
   251  func (it *Dynamic) IsSliceOrArray() bool {
   252  	k := it.ReflectKind()
   253  
   254  	return k == reflect.Slice || k == reflect.Array
   255  }
   256  
   257  func (it *Dynamic) IsSliceOrArrayOrMap() bool {
   258  	k := it.ReflectKind()
   259  
   260  	return k == reflect.Slice ||
   261  		k == reflect.Array ||
   262  		k == reflect.Map
   263  }
   264  
   265  func (it *Dynamic) IsMap() bool {
   266  	return it.ReflectKind() == reflect.Map
   267  }
   268  
   269  func (it *Dynamic) IsNull() bool {
   270  	return it.innerData == nil
   271  }
   272  
   273  func (it *Dynamic) IsValid() bool {
   274  	return it.isValid
   275  }
   276  
   277  func (it *Dynamic) IsInvalid() bool {
   278  	return !it.isValid
   279  }
   280  
   281  func (it *Dynamic) Loop(
   282  	loopProcessorFunc func(index int, item interface{}) (isBreak bool),
   283  ) (isCalled bool) {
   284  	if it.IsInvalid() || it.IsNull() || it.Length() <= 0 {
   285  		return false
   286  	}
   287  
   288  	length := it.Length()
   289  	rv := *it.ReflectValue()
   290  
   291  	for i := 0; i < length; i++ {
   292  		isBreak := loopProcessorFunc(
   293  			i,
   294  			rv.Index(i).Interface())
   295  
   296  		if isBreak {
   297  			return true
   298  		}
   299  	}
   300  
   301  	return true
   302  }
   303  
   304  func (it *Dynamic) FilterAsDynamicCollection(
   305  	filterFunc func(index int, itemAsDynamic Dynamic) (isTake, isBreak bool),
   306  ) *DynamicCollection {
   307  	if it.IsInvalid() || it.IsNull() || it.Length() <= 0 {
   308  		return EmptyDynamicCollection()
   309  	}
   310  
   311  	length := it.Length()
   312  	rv := *it.ReflectValue()
   313  	dynamicCollection := NewDynamicCollection(length / 2)
   314  
   315  	for i := 0; i < length; i++ {
   316  		currentRv := rv.Index(i)
   317  		valInf := currentRv.Interface()
   318  		currentDynamic := NewDynamic(valInf, currentRv.IsValid())
   319  
   320  		isTake, isBreak := filterFunc(
   321  			i,
   322  			currentDynamic)
   323  
   324  		if isTake {
   325  			dynamicCollection.Add(currentDynamic)
   326  		}
   327  
   328  		if isBreak {
   329  			return dynamicCollection
   330  		}
   331  	}
   332  
   333  	return dynamicCollection
   334  }
   335  
   336  func (it *Dynamic) LoopMap(
   337  	mapLoopProcessorFunc func(index int, key, value interface{}) (isBreak bool),
   338  ) (isCalled bool) {
   339  	if it.IsInvalid() || it.IsNull() || it.Length() <= 0 {
   340  		return false
   341  	}
   342  
   343  	rv := *it.ReflectValue()
   344  	mapIterator := rv.MapRange()
   345  	index := 0
   346  	for mapIterator.Next() {
   347  		k := mapIterator.Key()
   348  		v := mapIterator.Value()
   349  		isBreak := mapLoopProcessorFunc(index, k.Interface(), v.Interface())
   350  
   351  		if isBreak {
   352  			return true
   353  		}
   354  
   355  		index++
   356  	}
   357  
   358  	return true
   359  }
   360  
   361  func (it *Dynamic) ConvertUsingFunc(
   362  	converter SimpleInOutConverter,
   363  	expectedType reflect.Type,
   364  ) *SimpleResult {
   365  	return converter(it.innerData, expectedType)
   366  }
   367  
   368  func (it Dynamic) NonPtr() Dynamic {
   369  	return it
   370  }
   371  
   372  func (it *Dynamic) Ptr() *Dynamic {
   373  	return it
   374  }
   375  
   376  func (it *Dynamic) Bytes() (rawBytes []byte, isSuccess bool) {
   377  	if it == nil {
   378  		return nil, false
   379  	}
   380  
   381  	rawBytes, isSuccess = it.innerData.([]byte)
   382  
   383  	if isSuccess {
   384  		return rawBytes, isSuccess
   385  	}
   386  
   387  	rawBytes, err := json.Marshal(it.innerData)
   388  
   389  	return rawBytes, err != nil
   390  }
   391  
   392  func (it *Dynamic) ReflectSetTo(toPointer interface{}) error {
   393  	if it == nil {
   394  		return defaulterr.NilResult
   395  	}
   396  
   397  	return ReflectSetFromTo(
   398  		it.innerData,
   399  		toPointer)
   400  }
   401  
   402  func (it *Dynamic) Deserialize(jsonBytes []byte) (deserialized *Dynamic, err error) {
   403  	if it == nil {
   404  		return InvalidDynamicPtr(), defaulterr.UnmarshallingFailedDueToNilOrEmpty
   405  	}
   406  
   407  	err = corejson.
   408  		Deserialize.
   409  		UsingBytes(jsonBytes, it.innerData)
   410  
   411  	it.isValid = err == nil
   412  
   413  	return it, err
   414  }
   415  
   416  func (it *Dynamic) ValueMarshal() (jsonBytes []byte, err error) {
   417  	if it == nil {
   418  		return nil, defaulterr.NilResult
   419  	}
   420  
   421  	return corejson.
   422  		Serialize.
   423  		ToBytesErr(it.innerData)
   424  }
   425  
   426  func (it *Dynamic) JsonPayloadMust() (jsonBytes []byte) {
   427  	return corejson.
   428  		Serialize.
   429  		ToSafeBytesMust(it.innerData)
   430  }
   431  
   432  // JsonBytesPtr returns empty string on nil.
   433  // no error on nil.
   434  func (it *Dynamic) JsonBytesPtr() (jsonBytesPtr *[]byte, err error) {
   435  	if it.IsNull() {
   436  		return &[]byte{}, nil
   437  	}
   438  
   439  	marshalledBytes, e := json.Marshal(it.innerData)
   440  
   441  	if e != nil {
   442  		return &[]byte{}, e
   443  	}
   444  
   445  	return &marshalledBytes, nil
   446  }
   447  
   448  func (it *Dynamic) MarshalJSON() ([]byte, error) {
   449  	return corejson.
   450  		Serialize.
   451  		ToBytesErr(it.innerData)
   452  }
   453  
   454  func (it *Dynamic) UnmarshalJSON(data []byte) error {
   455  	if it == nil {
   456  		return defaulterr.UnmarshallingFailedDueToNilOrEmpty
   457  	}
   458  
   459  	err := corejson.
   460  		Deserialize.
   461  		UsingBytes(data, it.innerData)
   462  
   463  	it.isValid = err == nil
   464  
   465  	return err
   466  }
   467  
   468  func (it *Dynamic) JsonModel() interface{} {
   469  	return it.innerData
   470  }
   471  
   472  func (it *Dynamic) JsonModelAny() interface{} {
   473  	return it.JsonModel()
   474  }
   475  
   476  func (it Dynamic) Json() corejson.Result {
   477  	return corejson.New(it)
   478  }
   479  
   480  func (it Dynamic) JsonPtr() *corejson.Result {
   481  	return corejson.NewPtr(it)
   482  }
   483  
   484  //goland:noinspection GoLinterLocal
   485  func (it *Dynamic) ParseInjectUsingJson(
   486  	jsonResult *corejson.Result,
   487  ) (*Dynamic, error) {
   488  	err := jsonResult.Unmarshal(it)
   489  
   490  	if err != nil {
   491  		return nil, err
   492  	}
   493  
   494  	return it, nil
   495  }
   496  
   497  // ParseInjectUsingJsonMust Panic if error
   498  //goland:noinspection GoLinterLocal
   499  func (it *Dynamic) ParseInjectUsingJsonMust(
   500  	jsonResult *corejson.Result,
   501  ) *Dynamic {
   502  	newUsingJson, err :=
   503  		it.ParseInjectUsingJson(jsonResult)
   504  
   505  	if err != nil {
   506  		panic(err)
   507  	}
   508  
   509  	return newUsingJson
   510  }
   511  
   512  func (it *Dynamic) JsonParseSelfInject(
   513  	jsonResult *corejson.Result,
   514  ) error {
   515  	_, err := it.ParseInjectUsingJson(
   516  		jsonResult,
   517  	)
   518  
   519  	return err
   520  }
   521  
   522  func (it *Dynamic) IsStringType() bool {
   523  	_, isString := it.innerData.(string)
   524  
   525  	return isString
   526  }
   527  
   528  func (it *Dynamic) JsonBytes() (jsonBytesPtr []byte, err error) {
   529  	allBytes, err := it.JsonBytesPtr()
   530  
   531  	if err != nil {
   532  		return []byte{}, err
   533  	}
   534  
   535  	return *allBytes, err
   536  }
   537  
   538  func (it *Dynamic) JsonString() (jsonString string, err error) {
   539  	marshalledBytes, err := it.JsonBytes()
   540  
   541  	if err != nil {
   542  		return constants.EmptyString, err
   543  	}
   544  
   545  	return string(marshalledBytes), err
   546  }
   547  
   548  func (it *Dynamic) JsonStringMust() string {
   549  	marshalledBytes, err := it.JsonBytes()
   550  
   551  	if err != nil {
   552  		errcore.
   553  			MarshallingFailedType.
   554  			HandleUsingPanic(err.Error(), it.innerDataString)
   555  	}
   556  
   557  	return string(marshalledBytes)
   558  }
   559  
   560  func (it Dynamic) Clone() Dynamic {
   561  	return NewDynamic(
   562  		it.innerData,
   563  		it.isValid)
   564  }
   565  
   566  func (it *Dynamic) ClonePtr() *Dynamic {
   567  	if it == nil {
   568  		return nil
   569  	}
   570  
   571  	return NewDynamicPtr(
   572  		it.innerData,
   573  		it.isValid)
   574  }
   575  
   576  func (it *Dynamic) ValueInt() int {
   577  	casted, isSuccess := it.innerData.(int)
   578  
   579  	if isSuccess {
   580  		return casted
   581  	}
   582  
   583  	return constants.InvalidValue
   584  }
   585  
   586  func (it *Dynamic) ValueUInt() uint {
   587  	casted, isSuccess := it.innerData.(uint)
   588  
   589  	if isSuccess {
   590  		return casted
   591  	}
   592  
   593  	return constants.Zero
   594  }
   595  
   596  func (it *Dynamic) ValueStrings() []string {
   597  	casted, isSuccess := it.innerData.([]string)
   598  
   599  	if isSuccess {
   600  		return casted
   601  	}
   602  
   603  	return nil
   604  }
   605  
   606  func (it *Dynamic) ValueBool() bool {
   607  	casted, isSuccess := it.innerData.(bool)
   608  
   609  	if isSuccess {
   610  		return casted
   611  	}
   612  
   613  	return false
   614  }
   615  
   616  func (it *Dynamic) ValueInt64() int64 {
   617  	casted, isSuccess := it.innerData.(int64)
   618  
   619  	if isSuccess {
   620  		return casted
   621  	}
   622  
   623  	return constants.InvalidValue
   624  }
   625  
   626  func (it *Dynamic) ValueNullErr() error {
   627  	if it == nil {
   628  		return errcore.
   629  			CannotBeNilOrEmptyType.
   630  			ErrorNoRefs("Dynamic is nil or null")
   631  	}
   632  
   633  	if reflectinternal.IsNull(it.innerData) {
   634  		return errcore.
   635  			CannotBeNilOrEmptyType.
   636  			ErrorNoRefs("Dynamic internal data is nil.")
   637  	}
   638  
   639  	return nil
   640  }
   641  
   642  func (it *Dynamic) ValueString() string {
   643  	if it == nil || it.innerData == nil {
   644  		return constants.EmptyString
   645  	}
   646  
   647  	currentString, isString := it.innerData.(string)
   648  
   649  	if isString {
   650  		return currentString
   651  	}
   652  
   653  	return fmt.Sprintf(
   654  		constants.SprintValueFormat,
   655  		it.innerData,
   656  	)
   657  }