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

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