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 }