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

     1  package coredynamic
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"math"
     7  	"reflect"
     8  	"strings"
     9  	"sync"
    10  
    11  	"gitlab.com/evatix-go/core/constants"
    12  	"gitlab.com/evatix-go/core/coredata/corejson"
    13  	"gitlab.com/evatix-go/core/defaultcapacity"
    14  	"gitlab.com/evatix-go/core/errcore"
    15  	"gitlab.com/evatix-go/core/internal/reflectinternal"
    16  	"gitlab.com/evatix-go/core/internal/strutilinternal"
    17  	"gitlab.com/evatix-go/core/pagingutil"
    18  )
    19  
    20  type AnyCollection struct {
    21  	items []interface{}
    22  }
    23  
    24  func EmptyAnyCollection() *AnyCollection {
    25  	return NewAnyCollection(constants.Zero)
    26  }
    27  
    28  func NewAnyCollection(capacity int) *AnyCollection {
    29  	slice := make([]interface{}, 0, capacity)
    30  
    31  	return &AnyCollection{items: slice}
    32  }
    33  
    34  func (it *AnyCollection) At(index int) interface{} {
    35  	return it.items[index]
    36  }
    37  
    38  func (it *AnyCollection) ReflectSetAt(
    39  	index int,
    40  	toPointerOrBytesSet interface{},
    41  ) error {
    42  	item := it.items[index]
    43  
    44  	return ReflectSetFromTo(item, toPointerOrBytesSet)
    45  }
    46  
    47  func (it *AnyCollection) AtAsDynamic(index int) Dynamic {
    48  	return NewDynamic(it.items[index], true)
    49  }
    50  
    51  func (it *AnyCollection) Items() []interface{} {
    52  	if it.IsEmpty() {
    53  		return []interface{}{}
    54  	}
    55  
    56  	return it.items
    57  }
    58  
    59  func (it *AnyCollection) DynamicItems() []Dynamic {
    60  	if it.IsEmpty() {
    61  		return []Dynamic{}
    62  	}
    63  
    64  	slice := make([]Dynamic, it.Length())
    65  
    66  	for i, item := range it.items {
    67  		slice[i] = NewDynamic(item, true)
    68  	}
    69  
    70  	return slice
    71  }
    72  
    73  func (it *AnyCollection) DynamicCollection() *DynamicCollection {
    74  	if it.IsEmpty() {
    75  		return EmptyDynamicCollection()
    76  	}
    77  
    78  	return &DynamicCollection{
    79  		items: it.DynamicItems(),
    80  	}
    81  }
    82  
    83  func (it *AnyCollection) FirstDynamic() interface{} {
    84  	return it.items[0]
    85  }
    86  
    87  func (it *AnyCollection) First() interface{} {
    88  	return it.items[0]
    89  }
    90  
    91  func (it *AnyCollection) LastDynamic() interface{} {
    92  	return it.items[it.LastIndex()]
    93  }
    94  
    95  func (it *AnyCollection) Last() interface{} {
    96  	return it.items[it.LastIndex()]
    97  }
    98  
    99  func (it *AnyCollection) FirstOrDefaultDynamic() interface{} {
   100  	return it.FirstOrDefault()
   101  }
   102  
   103  func (it *AnyCollection) FirstOrDefault() interface{} {
   104  	if it.IsEmpty() {
   105  		return nil
   106  	}
   107  
   108  	return it.First()
   109  }
   110  
   111  func (it *AnyCollection) LastOrDefaultDynamic() interface{} {
   112  	return it.LastOrDefault()
   113  }
   114  
   115  func (it *AnyCollection) LastOrDefault() interface{} {
   116  	if it.IsEmpty() {
   117  		return nil
   118  	}
   119  
   120  	return it.Last()
   121  }
   122  
   123  func (it *AnyCollection) SkipDynamic(skippingItemsCount int) interface{} {
   124  	return it.items[skippingItemsCount:]
   125  }
   126  
   127  func (it *AnyCollection) Skip(skippingItemsCount int) []interface{} {
   128  	return it.items[skippingItemsCount:]
   129  }
   130  
   131  func (it *AnyCollection) SkipCollection(skippingItemsCount int) *AnyCollection {
   132  	return &AnyCollection{
   133  		items: it.items[skippingItemsCount:],
   134  	}
   135  }
   136  
   137  func (it *AnyCollection) TakeDynamic(takeDynamicItems int) interface{} {
   138  	return it.items[:takeDynamicItems]
   139  }
   140  
   141  func (it *AnyCollection) Take(takeDynamicItems int) []interface{} {
   142  	return it.items[:takeDynamicItems]
   143  }
   144  
   145  func (it *AnyCollection) TakeCollection(takeDynamicItems int) *AnyCollection {
   146  	return &AnyCollection{
   147  		items: it.items[:takeDynamicItems],
   148  	}
   149  }
   150  
   151  func (it *AnyCollection) LimitCollection(limit int) *AnyCollection {
   152  	return &AnyCollection{
   153  		items: it.items[:limit],
   154  	}
   155  }
   156  
   157  func (it *AnyCollection) SafeLimitCollection(limit int) *AnyCollection {
   158  	limit = defaultcapacity.
   159  		MaxLimit(it.Length(), limit)
   160  
   161  	return &AnyCollection{
   162  		items: it.items[:limit],
   163  	}
   164  }
   165  
   166  func (it *AnyCollection) LimitDynamic(limit int) interface{} {
   167  	return it.Take(limit)
   168  }
   169  
   170  func (it *AnyCollection) Limit(limit int) []interface{} {
   171  	return it.Take(limit)
   172  }
   173  
   174  func (it *AnyCollection) Length() int {
   175  	if it == nil {
   176  		return 0
   177  	}
   178  
   179  	return len(it.items)
   180  }
   181  
   182  func (it *AnyCollection) Count() int {
   183  	return it.Length()
   184  }
   185  
   186  func (it *AnyCollection) IsEmpty() bool {
   187  	if it == nil {
   188  		return true
   189  	}
   190  
   191  	return len(it.items) == 0
   192  }
   193  
   194  func (it *AnyCollection) HasAnyItem() bool {
   195  	return !it.IsEmpty()
   196  }
   197  
   198  func (it *AnyCollection) LastIndex() int {
   199  	return it.Length() - 1
   200  }
   201  
   202  func (it *AnyCollection) HasIndex(index int) bool {
   203  	return it.LastIndex() >= index
   204  }
   205  
   206  func (it *AnyCollection) ListStringsPtr(isIncludeFieldName bool) *[]string {
   207  	slice := make([]string, constants.Zero, it.Length()+1)
   208  
   209  	for _, anyItem := range it.items {
   210  		str := strutilinternal.AnyToStringUsing(
   211  			isIncludeFieldName,
   212  			anyItem)
   213  
   214  		slice = append(slice, str)
   215  	}
   216  
   217  	return &slice
   218  }
   219  
   220  func (it *AnyCollection) ListStrings(isIncludeFieldName bool) []string {
   221  	return *it.ListStringsPtr(isIncludeFieldName)
   222  }
   223  
   224  func (it *AnyCollection) RemoveAt(index int) (isSuccess bool) {
   225  	if !it.HasIndex(index) {
   226  		return false
   227  	}
   228  
   229  	items := it.items
   230  	it.items = append(
   231  		items[:index],
   232  		items[index+constants.One:]...)
   233  
   234  	return true
   235  }
   236  
   237  func (it *AnyCollection) Loop(
   238  	isRunAsync bool,
   239  	loopProcessorFunc func(index int, item interface{}) (isBreak bool), // break will not work on async
   240  ) *AnyCollection {
   241  	if it.IsEmpty() {
   242  		return it
   243  	}
   244  
   245  	length := it.Length()
   246  
   247  	if isRunAsync {
   248  		wg := sync.WaitGroup{}
   249  		wg.Add(length)
   250  		wrappedFunc := func(index int) {
   251  			loopProcessorFunc(index, it.items[index])
   252  
   253  			wg.Done()
   254  		}
   255  
   256  		for index := 0; index < length; index++ {
   257  			go wrappedFunc(index)
   258  		}
   259  
   260  		wg.Wait()
   261  
   262  		return it
   263  	}
   264  
   265  	for index := 0; index < it.Length(); index++ {
   266  		isBreak := loopProcessorFunc(index, it.items[index])
   267  
   268  		if isBreak {
   269  			return it
   270  		}
   271  	}
   272  
   273  	return it
   274  }
   275  
   276  func (it *AnyCollection) LoopDynamic(
   277  	isRunAsync bool,
   278  	loopProcessorFunc func(index int, item Dynamic) (isBreak bool), // break will not work on async
   279  ) *AnyCollection {
   280  	if it.IsEmpty() {
   281  		return it
   282  	}
   283  
   284  	length := it.Length()
   285  
   286  	if isRunAsync {
   287  		wg := sync.WaitGroup{}
   288  		wg.Add(length)
   289  		wrappedFunc := func(index int) {
   290  			currentItem := it.items[index]
   291  			dynamic := NewDynamic(
   292  				currentItem,
   293  				reflectinternal.IsNotNull(currentItem))
   294  
   295  			loopProcessorFunc(index, dynamic)
   296  
   297  			wg.Done()
   298  		}
   299  
   300  		for index := 0; index < length; index++ {
   301  			go wrappedFunc(index)
   302  		}
   303  
   304  		wg.Wait()
   305  
   306  		return it
   307  	}
   308  
   309  	for index := 0; index < it.Length(); index++ {
   310  		dynamic := NewDynamic(
   311  			it.items[index],
   312  			reflectinternal.IsNotNull(it.items[index]))
   313  		isBreak := loopProcessorFunc(index, dynamic)
   314  
   315  		if isBreak {
   316  			return it
   317  		}
   318  	}
   319  
   320  	return it
   321  }
   322  
   323  func (it *AnyCollection) AddAny(anyItem interface{}, isValid bool) *AnyCollection {
   324  	it.items = append(
   325  		it.items,
   326  		NewDynamic(anyItem, isValid))
   327  
   328  	return it
   329  }
   330  
   331  func (it *AnyCollection) AddAnyItemsWithTypeValidation(
   332  	isContinueOnError,
   333  	isNullNotAllowed bool,
   334  	expectedType reflect.Type,
   335  	anyItems ...interface{},
   336  ) error {
   337  	if len(anyItems) == 0 {
   338  		return nil
   339  	}
   340  
   341  	if isContinueOnError {
   342  		var sliceErr []string
   343  
   344  		for _, anyItem := range anyItems {
   345  			err := it.AddAnyWithTypeValidation(
   346  				isNullNotAllowed,
   347  				expectedType,
   348  				anyItem)
   349  
   350  			if err != nil {
   351  				sliceErr = append(sliceErr, err.Error())
   352  			}
   353  		}
   354  
   355  		return errcore.SliceToError(sliceErr)
   356  	}
   357  
   358  	for _, anyItem := range anyItems {
   359  		err := it.AddAnyWithTypeValidation(
   360  			isNullNotAllowed,
   361  			expectedType,
   362  			anyItem)
   363  
   364  		if err != nil {
   365  			return err
   366  		}
   367  	}
   368  
   369  	return nil
   370  }
   371  
   372  func (it *AnyCollection) AddAnyWithTypeValidation(
   373  	isNullNotAllowed bool,
   374  	expectedType reflect.Type,
   375  	anyItem interface{},
   376  ) error {
   377  	err := ReflectTypeValidation(
   378  		isNullNotAllowed,
   379  		expectedType,
   380  		anyItem)
   381  
   382  	if err != nil {
   383  		return err
   384  	}
   385  
   386  	it.items = append(
   387  		it.items,
   388  		anyItem)
   389  
   390  	return nil
   391  }
   392  
   393  func (it *AnyCollection) AddNonNull(anyItem interface{}) *AnyCollection {
   394  	if anyItem == nil {
   395  		return it
   396  	}
   397  
   398  	it.items = append(
   399  		it.items,
   400  		anyItem)
   401  
   402  	return it
   403  }
   404  
   405  func (it *AnyCollection) AddNonNullDynamic(anyItem interface{}, isValid bool) *AnyCollection {
   406  	if anyItem == nil {
   407  		return it
   408  	}
   409  
   410  	it.items = append(
   411  		it.items,
   412  		NewDynamic(anyItem, isValid))
   413  
   414  	return it
   415  }
   416  
   417  func (it *AnyCollection) AddAnyManyDynamic(anyItems ...interface{}) *AnyCollection {
   418  	if anyItems == nil {
   419  		return it
   420  	}
   421  
   422  	for _, item := range anyItems {
   423  		it.items = append(
   424  			it.items,
   425  			NewDynamic(item, true))
   426  	}
   427  
   428  	return it
   429  }
   430  
   431  func (it *AnyCollection) Add(anyItem interface{}) *AnyCollection {
   432  	it.items = append(it.items, anyItem)
   433  
   434  	return it
   435  }
   436  
   437  func (it *AnyCollection) AddAnySliceFromSingleItem(
   438  	sliceList interface{},
   439  ) *AnyCollection {
   440  	if sliceList == nil {
   441  		return it
   442  	}
   443  
   444  	items := AnySliceValToInterfacesAsync(sliceList)
   445  
   446  	return it.AddMany(items...)
   447  }
   448  
   449  func (it *AnyCollection) AddMany(anyItems ...interface{}) *AnyCollection {
   450  	if anyItems == nil {
   451  		return it
   452  	}
   453  
   454  	for _, anyItem := range anyItems {
   455  		if anyItem == nil {
   456  			continue
   457  		}
   458  
   459  		it.items = append(it.items, anyItem)
   460  	}
   461  
   462  	return it
   463  }
   464  
   465  func (it *AnyCollection) JsonString() (jsonString string, err error) {
   466  	toBytes, err := json.Marshal(it.items)
   467  
   468  	if err != nil {
   469  		return constants.EmptyString, nil
   470  	}
   471  
   472  	return string(toBytes), nil
   473  }
   474  
   475  func (it *AnyCollection) JsonStringMust() string {
   476  	toString, err := it.JsonString()
   477  
   478  	if err != nil {
   479  		errcore.
   480  			MarshallingFailedType.
   481  			HandleUsingPanic(err.Error(), it.items)
   482  	}
   483  
   484  	return toString
   485  }
   486  
   487  func (it *AnyCollection) MarshalJSON() ([]byte, error) {
   488  	return json.Marshal(it.JsonModelAny())
   489  }
   490  
   491  func (it *AnyCollection) UnmarshalJSON(data []byte) error {
   492  	var dataModelItems []interface{}
   493  	err := json.Unmarshal(data, &dataModelItems)
   494  
   495  	if err == nil {
   496  		it.items = dataModelItems
   497  	}
   498  
   499  	return err
   500  }
   501  
   502  func (it *AnyCollection) JsonResultsCollection() *corejson.ResultsCollection {
   503  	jsonResultsCollection := corejson.NewResultsCollection.UsingCap(it.Length())
   504  
   505  	if it.IsEmpty() {
   506  		return jsonResultsCollection
   507  	}
   508  
   509  	for _, dynamicInstance := range it.items {
   510  		jsonResultsCollection.AddAny(
   511  			dynamicInstance)
   512  	}
   513  
   514  	return jsonResultsCollection
   515  }
   516  
   517  func (it *AnyCollection) JsonResultsPtrCollection() *corejson.ResultsPtrCollection {
   518  	jsonResultsCollection := corejson.
   519  		NewResultsPtrCollection.
   520  		UsingCap(it.Length())
   521  
   522  	if it.IsEmpty() {
   523  		return jsonResultsCollection
   524  	}
   525  
   526  	for _, dynamicInstance := range it.items {
   527  		jsonResultsCollection.AddAny(
   528  			dynamicInstance)
   529  	}
   530  
   531  	return jsonResultsCollection
   532  }
   533  
   534  func (it *AnyCollection) GetPagesSize(
   535  	eachPageSize int,
   536  ) int {
   537  	length := it.Length()
   538  
   539  	pagesPossibleFloat := float64(length) / float64(eachPageSize)
   540  	pagesPossibleCeiling := int(math.Ceil(pagesPossibleFloat))
   541  
   542  	return pagesPossibleCeiling
   543  }
   544  
   545  func (it *AnyCollection) GetPagedCollection(
   546  	eachPageSize int,
   547  ) []*AnyCollection {
   548  	length := it.Length()
   549  
   550  	if length < eachPageSize {
   551  		return []*AnyCollection{
   552  			it,
   553  		}
   554  	}
   555  
   556  	pagesPossibleFloat := float64(length) / float64(eachPageSize)
   557  	pagesPossibleCeiling := int(math.Ceil(pagesPossibleFloat))
   558  	collectionOfCollection := make(
   559  		[]*AnyCollection,
   560  		pagesPossibleCeiling)
   561  
   562  	wg := sync.WaitGroup{}
   563  	addPagedItemsFunc := func(oneBasedPageIndex int) {
   564  		pagedCollection := it.GetSinglePageCollection(
   565  			eachPageSize,
   566  			oneBasedPageIndex,
   567  		)
   568  
   569  		collectionOfCollection[oneBasedPageIndex-1] = pagedCollection
   570  
   571  		wg.Done()
   572  	}
   573  
   574  	wg.Add(pagesPossibleCeiling)
   575  	for i := 1; i <= pagesPossibleCeiling; i++ {
   576  		go addPagedItemsFunc(i)
   577  	}
   578  
   579  	wg.Wait()
   580  
   581  	return collectionOfCollection
   582  }
   583  
   584  func (it *AnyCollection) GetPagingInfo(
   585  	eachPageSize int,
   586  	pageIndex int,
   587  ) pagingutil.PagingInfo {
   588  	return pagingutil.GetPagingInfo(pagingutil.PagingRequest{
   589  		Length:       it.Length(),
   590  		PageIndex:    pageIndex,
   591  		EachPageSize: eachPageSize,
   592  	})
   593  }
   594  
   595  // GetSinglePageCollection PageIndex is one based index. Should be above or equal 1
   596  func (it *AnyCollection) GetSinglePageCollection(
   597  	eachPageSize int,
   598  	pageIndex int,
   599  ) *AnyCollection {
   600  	length := it.Length()
   601  
   602  	if length < eachPageSize {
   603  		return it
   604  	}
   605  
   606  	pageInfo := it.GetPagingInfo(
   607  		eachPageSize,
   608  		pageIndex)
   609  
   610  	list := it.items[pageInfo.SkipItems:pageInfo.EndingLength]
   611  
   612  	return &AnyCollection{
   613  		items: list,
   614  	}
   615  }
   616  
   617  func (it *AnyCollection) JsonModel() []interface{} {
   618  	return it.items
   619  }
   620  
   621  func (it *AnyCollection) JsonModelAny() interface{} {
   622  	return it.JsonModel()
   623  }
   624  
   625  func (it AnyCollection) Json() corejson.Result {
   626  	return corejson.New(it)
   627  }
   628  
   629  func (it AnyCollection) JsonPtr() *corejson.Result {
   630  	return corejson.NewPtr(it)
   631  }
   632  
   633  func (it *AnyCollection) ParseInjectUsingJson(
   634  	jsonResult *corejson.Result,
   635  ) (*AnyCollection, error) {
   636  	err := jsonResult.Unmarshal(it)
   637  
   638  	if err != nil {
   639  		return nil, err
   640  	}
   641  
   642  	return it, nil
   643  }
   644  
   645  func (it *AnyCollection) ParseInjectUsingJsonMust(
   646  	jsonResult *corejson.Result,
   647  ) *AnyCollection {
   648  	newUsingJson, err :=
   649  		it.ParseInjectUsingJson(jsonResult)
   650  
   651  	if err != nil {
   652  		panic(err)
   653  	}
   654  
   655  	return newUsingJson
   656  }
   657  
   658  func (it *AnyCollection) JsonParseSelfInject(
   659  	jsonResult *corejson.Result,
   660  ) error {
   661  	_, err := it.ParseInjectUsingJson(
   662  		jsonResult,
   663  	)
   664  
   665  	return err
   666  }
   667  
   668  func (it *AnyCollection) Strings() []string {
   669  	slice := make([]string, it.Length())
   670  
   671  	if it.IsEmpty() {
   672  		return slice
   673  	}
   674  
   675  	for i, item := range it.items {
   676  		slice[i] = fmt.Sprintf(
   677  			constants.SprintValueFormat,
   678  			item)
   679  	}
   680  
   681  	return slice
   682  }
   683  
   684  func (it *AnyCollection) String() string {
   685  	return strings.Join(it.Strings(), constants.NewLineUnix)
   686  }