gitlab.com/evatix-go/core@v1.3.55/coredata/corestr/LinkedCollections.go (about)

     1  package corestr
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  	"sync"
     8  
     9  	"gitlab.com/evatix-go/core/constants"
    10  	"gitlab.com/evatix-go/core/coredata/corejson"
    11  	"gitlab.com/evatix-go/core/coreindexes"
    12  	"gitlab.com/evatix-go/core/errcore"
    13  )
    14  
    15  type LinkedCollections struct {
    16  	head, tail *LinkedCollectionNode
    17  	length     int
    18  	sync.Mutex
    19  }
    20  
    21  func (it *LinkedCollections) Tail() *LinkedCollectionNode {
    22  	return it.tail
    23  }
    24  
    25  func (it *LinkedCollections) Head() *LinkedCollectionNode {
    26  	return it.head
    27  }
    28  
    29  func (it *LinkedCollections) First() *Collection {
    30  	return it.head.Element
    31  }
    32  
    33  func (it *LinkedCollections) Single() *Collection {
    34  	return it.head.Element
    35  }
    36  
    37  func (it *LinkedCollections) Last() *Collection {
    38  	return it.tail.Element
    39  }
    40  
    41  func (it *LinkedCollections) LastOrDefault() *Collection {
    42  	if it.IsEmpty() {
    43  		return Empty.Collection()
    44  	}
    45  
    46  	return it.tail.Element
    47  }
    48  
    49  func (it *LinkedCollections) FirstOrDefault() *Collection {
    50  	if it.IsEmpty() {
    51  		return Empty.Collection()
    52  	}
    53  
    54  	return it.head.Element
    55  }
    56  
    57  func (it *LinkedCollections) Length() int {
    58  	return it.length
    59  }
    60  
    61  // AllIndividualItemsLength including all nested ones
    62  func (it *LinkedCollections) AllIndividualItemsLength() int {
    63  	allLengthSum := 0
    64  
    65  	var processor LinkedCollectionSimpleProcessor = func(
    66  		arg *LinkedCollectionProcessorParameter,
    67  	) (isBreak bool) {
    68  		allLengthSum += arg.CurrentNode.Element.Length()
    69  
    70  		return false
    71  	}
    72  
    73  	it.Loop(processor)
    74  
    75  	return allLengthSum
    76  }
    77  
    78  func (it *LinkedCollections) incrementLength() int {
    79  	it.length++
    80  
    81  	return it.length
    82  }
    83  
    84  func (it *LinkedCollections) setLengthToZero() int {
    85  	it.length = 0
    86  
    87  	return it.length
    88  }
    89  
    90  func (it *LinkedCollections) setLength(number int) int {
    91  	it.length = number
    92  
    93  	return it.length
    94  }
    95  
    96  func (it *LinkedCollections) decrementLength() int {
    97  	it.length--
    98  
    99  	return it.length
   100  }
   101  
   102  func (it *LinkedCollections) incrementLengthLock() {
   103  	it.Lock()
   104  	it.length++
   105  	it.Unlock()
   106  }
   107  
   108  func (it *LinkedCollections) incrementLengthUsingNumber(number int) int {
   109  	it.length += number
   110  
   111  	return it.length
   112  }
   113  
   114  func (it *LinkedCollections) LengthLock() int {
   115  	it.Lock()
   116  	defer it.Unlock()
   117  
   118  	return it.length
   119  }
   120  
   121  func (it *LinkedCollections) IsEqualsPtr(
   122  	anotherLinkedCollections *LinkedCollections,
   123  ) bool {
   124  	if anotherLinkedCollections == nil {
   125  		return false
   126  	}
   127  
   128  	if it == anotherLinkedCollections {
   129  		return true
   130  	}
   131  
   132  	if it.IsEmpty() && anotherLinkedCollections.IsEmpty() {
   133  		return true
   134  	}
   135  
   136  	if it.IsEmpty() || anotherLinkedCollections.IsEmpty() {
   137  		return false
   138  	}
   139  
   140  	if it.Length() != anotherLinkedCollections.Length() {
   141  		return false
   142  	}
   143  
   144  	leftNode := it.head
   145  	rightNode := anotherLinkedCollections.head
   146  
   147  	if leftNode == nil && rightNode == nil {
   148  		return true
   149  	}
   150  
   151  	if leftNode == nil || rightNode == nil {
   152  		return false
   153  	}
   154  
   155  	return leftNode.IsChainEqual(rightNode)
   156  }
   157  
   158  func (it *LinkedCollections) IsEmptyLock() bool {
   159  	it.Lock()
   160  	defer it.Unlock()
   161  
   162  	return it.head == nil || it.length == 0
   163  }
   164  
   165  func (it *LinkedCollections) IsEmpty() bool {
   166  	return it.head == nil || it.length == 0
   167  }
   168  
   169  func (it *LinkedCollections) HasItems() bool {
   170  	return it.head != nil &&
   171  		it.length > 0
   172  }
   173  
   174  // InsertAt BigO(n) expensive operation.
   175  func (it *LinkedCollections) InsertAt(
   176  	index int,
   177  	collection *Collection,
   178  ) *LinkedCollections {
   179  	if index < 1 {
   180  		return it.AddFront(collection)
   181  	}
   182  
   183  	node := it.IndexAt(index - 1)
   184  	it.AddAfterNode(node, collection)
   185  
   186  	return it
   187  }
   188  
   189  func (it *LinkedCollections) AddAsync(
   190  	collection *Collection,
   191  	wg *sync.WaitGroup,
   192  ) *LinkedCollections {
   193  	go func() {
   194  		it.Lock()
   195  		defer it.Unlock()
   196  		it.Add(collection)
   197  
   198  		wg.Done()
   199  	}()
   200  
   201  	return it
   202  }
   203  
   204  // AddsAsyncOnComplete Append back
   205  func (it *LinkedCollections) AddsAsyncOnComplete(
   206  	onComplete OnCompleteLinkedCollections,
   207  	isSkipOnNil bool,
   208  	collections ...*Collection,
   209  ) *LinkedCollections {
   210  	go func() {
   211  		it.Lock()
   212  		defer it.Unlock()
   213  
   214  		it.AppendCollectionsPointers(isSkipOnNil, &collections)
   215  
   216  		onComplete(it)
   217  	}()
   218  
   219  	return it
   220  }
   221  
   222  // AddsUsingProcessorAsyncOnComplete Append back
   223  func (it *LinkedCollections) AddsUsingProcessorAsyncOnComplete(
   224  	onComplete OnCompleteLinkedCollections,
   225  	processor AnyToCollectionProcessor,
   226  	isSkipOnNil bool,
   227  	anys ...interface{},
   228  ) *LinkedCollections {
   229  	go func() {
   230  		it.Lock()
   231  		defer it.Unlock()
   232  
   233  		if anys == nil && isSkipOnNil {
   234  			onComplete(it)
   235  
   236  			return
   237  		}
   238  
   239  		for i, any := range anys {
   240  			if any == nil && isSkipOnNil {
   241  				continue
   242  			}
   243  
   244  			collection := processor(any, i)
   245  			it.Add(collection)
   246  		}
   247  
   248  		onComplete(it)
   249  	}()
   250  
   251  	return it
   252  }
   253  
   254  // AddsUsingProcessorAsync Append back
   255  func (it *LinkedCollections) AddsUsingProcessorAsync(
   256  	wg *sync.WaitGroup,
   257  	processor AnyToCollectionProcessor,
   258  	isSkipOnNil bool,
   259  	anys ...interface{},
   260  ) *LinkedCollections {
   261  	go func() {
   262  		it.Lock()
   263  		defer it.Unlock()
   264  
   265  		if anys == nil && isSkipOnNil {
   266  			wg.Done()
   267  
   268  			return
   269  		}
   270  
   271  		for i, any := range anys {
   272  			if any == nil && isSkipOnNil {
   273  				continue
   274  			}
   275  
   276  			collection := processor(any, i)
   277  			it.Add(collection)
   278  		}
   279  
   280  		wg.Done()
   281  	}()
   282  
   283  	return it
   284  }
   285  
   286  func (it *LinkedCollections) AddLock(collection *Collection) *LinkedCollections {
   287  	it.Lock()
   288  	defer it.Unlock()
   289  
   290  	return it.Add(collection)
   291  }
   292  
   293  func (it *LinkedCollections) Add(collection *Collection) *LinkedCollections {
   294  	if it.IsEmpty() {
   295  		it.head = &LinkedCollectionNode{
   296  			Element: collection,
   297  			next:    nil,
   298  		}
   299  
   300  		it.tail = it.head
   301  		it.incrementLength()
   302  
   303  		return it
   304  	}
   305  
   306  	it.tail.next = &LinkedCollectionNode{
   307  		Element: collection,
   308  		next:    nil,
   309  	}
   310  
   311  	it.tail = it.tail.next
   312  	it.incrementLength()
   313  
   314  	return it
   315  }
   316  
   317  func (it *LinkedCollections) AddStringsLock(stringsItems ...string) *LinkedCollections {
   318  	if len(stringsItems) == 0 {
   319  		return it
   320  	}
   321  
   322  	it.Lock()
   323  	defer it.Unlock()
   324  
   325  	return it.AddStringsPtr(false, &stringsItems)
   326  }
   327  
   328  func (it *LinkedCollections) AddStrings(stringsItems ...string) *LinkedCollections {
   329  	if len(stringsItems) == 0 {
   330  		return it
   331  	}
   332  
   333  	collection := New.Collection.StringsOptions(false, stringsItems)
   334  
   335  	return it.Add(collection)
   336  }
   337  
   338  func (it *LinkedCollections) AddBackNode(node *LinkedCollectionNode) *LinkedCollections {
   339  	return it.AppendNode(node)
   340  }
   341  
   342  func (it *LinkedCollections) AppendNode(node *LinkedCollectionNode) *LinkedCollections {
   343  	if it.IsEmpty() {
   344  		it.head = node
   345  		it.tail = it.head
   346  		it.incrementLength()
   347  
   348  		return it
   349  	}
   350  
   351  	it.tail.next = node
   352  	it.tail = it.tail.next
   353  	it.incrementLength()
   354  
   355  	return it
   356  }
   357  
   358  func (it *LinkedCollections) AppendChainOfNodes(nodeHead *LinkedCollectionNode) *LinkedCollections {
   359  	endOfChain, length := nodeHead.EndOfChain()
   360  
   361  	if it.IsEmpty() {
   362  		it.head = nodeHead
   363  	} else {
   364  		it.tail.next = nodeHead
   365  	}
   366  
   367  	it.tail = endOfChain
   368  	it.incrementLengthUsingNumber(length)
   369  
   370  	return it
   371  }
   372  
   373  func (it *LinkedCollections) AppendChainOfNodesAsync(
   374  	nodeHead *LinkedCollectionNode,
   375  	wg *sync.WaitGroup,
   376  ) *LinkedCollections {
   377  	go func() {
   378  		it.Lock()
   379  		it.AppendChainOfNodes(nodeHead)
   380  		it.Unlock()
   381  
   382  		wg.Done()
   383  	}()
   384  
   385  	return it
   386  }
   387  
   388  func (it *LinkedCollections) PushBackLock(collection *Collection) *LinkedCollections {
   389  	return it.AddLock(collection)
   390  }
   391  
   392  func (it *LinkedCollections) PushBack(collection *Collection) *LinkedCollections {
   393  	return it.Add(collection)
   394  }
   395  
   396  func (it *LinkedCollections) Push(collection *Collection) *LinkedCollections {
   397  	return it.Add(collection)
   398  }
   399  
   400  func (it *LinkedCollections) PushFront(collection *Collection) *LinkedCollections {
   401  	return it.AddFront(collection)
   402  }
   403  
   404  func (it *LinkedCollections) AddFrontLock(collection *Collection) *LinkedCollections {
   405  	it.Lock()
   406  	defer it.Unlock()
   407  
   408  	return it.AddFront(collection)
   409  }
   410  
   411  func (it *LinkedCollections) AddFront(collection *Collection) *LinkedCollections {
   412  	if it.IsEmpty() {
   413  		return it.Add(collection)
   414  	}
   415  
   416  	node := &LinkedCollectionNode{
   417  		Element: collection,
   418  		next:    it.head,
   419  	}
   420  
   421  	it.head = node
   422  	it.incrementLength()
   423  
   424  	return it
   425  }
   426  
   427  func (it *LinkedCollections) AttachWithNode(
   428  	currentNode,
   429  	addingNode *LinkedCollectionNode,
   430  ) error {
   431  	if currentNode == nil {
   432  		return errcore.
   433  			CannotBeNilType.
   434  			Error(currentNodeCannotBeNull, nil)
   435  	}
   436  
   437  	if currentNode.next != nil {
   438  		return errcore.
   439  			ShouldBeNilType.
   440  			Error("CurrentNode.next", nil)
   441  	}
   442  
   443  	addingNode.next = currentNode.next
   444  	currentNode.next = addingNode
   445  	it.incrementLength()
   446  
   447  	return nil
   448  }
   449  
   450  func (it *LinkedCollections) AddAnother(
   451  	another *LinkedCollections,
   452  ) *LinkedCollections {
   453  	if another == nil || another.IsEmpty() {
   454  		return it
   455  	}
   456  
   457  	node := another.Head()
   458  	it.Add(node.Element)
   459  
   460  	for node.HasNext() {
   461  		node = node.Next()
   462  
   463  		it.Add(node.Element)
   464  	}
   465  
   466  	return it
   467  }
   468  
   469  // AddCollectionToNode iSkipOnNil
   470  func (it *LinkedCollections) AddCollectionToNode(
   471  	isSkipOnNull bool,
   472  	node *LinkedCollectionNode,
   473  	collection *Collection,
   474  ) *LinkedCollections {
   475  	return it.AddCollectionsToNode(
   476  		isSkipOnNull,
   477  		node,
   478  		collection)
   479  }
   480  
   481  func (it *LinkedCollections) GetNextNodes(count int) *[]*LinkedCollectionNode {
   482  	counter := 0
   483  
   484  	return it.Filter(
   485  		func(
   486  			arg *LinkedCollectionFilterParameter,
   487  		) *LinkedCollectionFilterResult {
   488  			isBreak := counter >= count-1
   489  
   490  			counter++
   491  			return &LinkedCollectionFilterResult{
   492  				Value:   arg.Node,
   493  				IsKeep:  true,
   494  				IsBreak: isBreak,
   495  			}
   496  		})
   497  }
   498  
   499  func (it *LinkedCollections) GetAllLinkedNodes() *[]*LinkedCollectionNode {
   500  	return it.Filter(
   501  		func(
   502  			arg *LinkedCollectionFilterParameter,
   503  		) *LinkedCollectionFilterResult {
   504  			return &LinkedCollectionFilterResult{
   505  				Value:   arg.Node,
   506  				IsKeep:  true,
   507  				IsBreak: false,
   508  			}
   509  		})
   510  }
   511  
   512  func (it *LinkedCollections) Loop(
   513  	simpleProcessor LinkedCollectionSimpleProcessor,
   514  ) *LinkedCollections {
   515  	length := it.Length()
   516  	if length == 0 {
   517  		return it
   518  	}
   519  
   520  	node := it.head
   521  	arg := &LinkedCollectionProcessorParameter{
   522  		Index:         0,
   523  		CurrentNode:   node,
   524  		PrevNode:      nil,
   525  		IsFirstIndex:  true,
   526  		IsEndingIndex: false,
   527  	}
   528  
   529  	isBreak := simpleProcessor(arg)
   530  
   531  	if isBreak {
   532  		return it
   533  	}
   534  
   535  	lenMinusOne := length - 1
   536  	index := 1
   537  	isEndingIndex := false
   538  
   539  	for node.HasNext() {
   540  		prev := node
   541  		node = node.Next()
   542  		isEndingIndex = lenMinusOne == index
   543  
   544  		arg2 := &LinkedCollectionProcessorParameter{
   545  			Index:         index,
   546  			CurrentNode:   node,
   547  			PrevNode:      prev,
   548  			IsFirstIndex:  false,
   549  			IsEndingIndex: isEndingIndex,
   550  		}
   551  
   552  		isBreak = simpleProcessor(arg2)
   553  
   554  		if isBreak {
   555  			return it
   556  		}
   557  
   558  		index++
   559  	}
   560  
   561  	return it
   562  }
   563  
   564  func (it *LinkedCollections) Filter(
   565  	filter LinkedCollectionFilter,
   566  ) *[]*LinkedCollectionNode {
   567  	length := it.Length()
   568  	list := make([]*LinkedCollectionNode, 0, length)
   569  
   570  	if length == 0 {
   571  		return &list
   572  	}
   573  
   574  	node := it.head
   575  	arg := &LinkedCollectionFilterParameter{
   576  		Node:  node,
   577  		Index: 0,
   578  	}
   579  
   580  	result := filter(arg)
   581  
   582  	if result.IsKeep {
   583  		list = append(list, result.Value)
   584  	}
   585  
   586  	if result.IsBreak {
   587  		return &list
   588  	}
   589  
   590  	index := 1
   591  	for node.HasNext() {
   592  		node = node.Next()
   593  
   594  		arg2 := &LinkedCollectionFilterParameter{
   595  			Node:  node,
   596  			Index: index,
   597  		}
   598  
   599  		result2 := filter(arg2)
   600  
   601  		if result2.IsKeep {
   602  			list = append(list, result2.Value)
   603  		}
   604  
   605  		if result2.IsBreak {
   606  			return &list
   607  		}
   608  
   609  		index++
   610  	}
   611  
   612  	return &list
   613  }
   614  
   615  func (it *LinkedCollections) FilterAsCollection(
   616  	filter LinkedCollectionFilter,
   617  	additionalCapacity int,
   618  ) *Collection {
   619  	items := it.Filter(filter)
   620  
   621  	if len(*items) == 0 {
   622  		return New.Collection.Empty()
   623  	}
   624  
   625  	allLength := 0
   626  
   627  	for _, node := range *items {
   628  		if node != nil && node.Element != nil {
   629  			allLength += node.Element.Length()
   630  		}
   631  	}
   632  
   633  	collection := New.Collection.Cap(allLength + additionalCapacity)
   634  
   635  	for _, node := range *items {
   636  		if node == nil || node.Element == nil {
   637  			continue
   638  		}
   639  
   640  		collection.AddCollection(node.Element)
   641  	}
   642  
   643  	return collection
   644  }
   645  
   646  func (it *LinkedCollections) FilterAsCollections(
   647  	filter LinkedCollectionFilter,
   648  ) *[]*Collection {
   649  	items := it.Filter(filter)
   650  	collections := make([]*Collection, len(*items))
   651  
   652  	for i := range *items {
   653  		collections[i] = (*items)[i].Element
   654  	}
   655  
   656  	return &collections
   657  }
   658  
   659  func (it *LinkedCollections) RemoveNodeByIndex(
   660  	removingIndex int,
   661  ) *LinkedCollections {
   662  	if removingIndex < 0 {
   663  		errcore.
   664  			CannotBeNegativeIndexType.
   665  			HandleUsingPanic(
   666  				"removeIndex was less than 0.",
   667  				removingIndex)
   668  	}
   669  
   670  	var singleProcessor LinkedCollectionSimpleProcessor = func(
   671  		arg *LinkedCollectionProcessorParameter,
   672  	) (isBreak bool) {
   673  		hasIndex := removingIndex == arg.Index
   674  
   675  		if !hasIndex {
   676  			return false
   677  		}
   678  
   679  		isBreak = hasIndex
   680  		it.decrementLength()
   681  
   682  		if arg.IsFirstIndex {
   683  			it.head =
   684  				arg.CurrentNode.next
   685  			arg.CurrentNode = nil
   686  			return isBreak
   687  		}
   688  
   689  		if arg.IsEndingIndex {
   690  			arg.PrevNode.next = nil
   691  			arg.CurrentNode = nil
   692  
   693  			return isBreak
   694  		}
   695  
   696  		arg.PrevNode.next = arg.CurrentNode.next
   697  		arg.CurrentNode = nil
   698  
   699  		return isBreak
   700  	}
   701  
   702  	return it.Loop(singleProcessor)
   703  }
   704  
   705  func (it *LinkedCollections) RemoveNodeByIndexes(
   706  	isIgnorePanic bool,
   707  	removingIndexes ...int,
   708  ) *LinkedCollections {
   709  	length := len(removingIndexes)
   710  
   711  	if length == 0 {
   712  		return it
   713  	}
   714  
   715  	if !isIgnorePanic && it.IsEmpty() && length > 0 {
   716  		errcore.
   717  			CannotRemoveIndexesFromEmptyCollectionType.
   718  			HandleUsingPanic("removingIndexes cannot be removed from Empty LinkedCollections.", removingIndexes)
   719  	}
   720  
   721  	nonChainedNodes := it.Filter(
   722  		func(arg *LinkedCollectionFilterParameter) *LinkedCollectionFilterResult {
   723  			hasIndex := coreindexes.HasIndexPlusRemoveIndex(removingIndexes, arg.Index)
   724  			if hasIndex {
   725  				// remove
   726  				return &LinkedCollectionFilterResult{
   727  					Value:   arg.Node,
   728  					IsKeep:  false,
   729  					IsBreak: false,
   730  				}
   731  			}
   732  
   733  			// not remove
   734  			return &LinkedCollectionFilterResult{
   735  				Value:   arg.Node,
   736  				IsKeep:  true,
   737  				IsBreak: false,
   738  			}
   739  		})
   740  
   741  	nonChainedCollection := &NonChainedLinkedCollectionNodes{
   742  		items:             nonChainedNodes,
   743  		isChainingApplied: false,
   744  	}
   745  
   746  	if nonChainedCollection.IsEmpty() {
   747  		return it
   748  	}
   749  
   750  	it.setLength(nonChainedCollection.Length())
   751  	it.head = nonChainedCollection.ApplyChaining().First()
   752  
   753  	return it
   754  }
   755  
   756  func (it *LinkedCollections) RemoveNode(
   757  	removingNode *LinkedCollectionNode,
   758  ) *LinkedCollections {
   759  	var processor LinkedCollectionSimpleProcessor = func(
   760  		arg *LinkedCollectionProcessorParameter,
   761  	) (isBreak bool) {
   762  		isSameNode := arg.CurrentNode == removingNode
   763  		if isSameNode && arg.IsFirstIndex {
   764  			it.head = arg.CurrentNode.next
   765  			it.decrementLength()
   766  
   767  			return true
   768  		}
   769  
   770  		if isSameNode {
   771  			arg.PrevNode.next = arg.CurrentNode.next
   772  			it.decrementLength()
   773  
   774  			return true
   775  		}
   776  
   777  		return false
   778  	}
   779  
   780  	return it.Loop(processor)
   781  }
   782  
   783  // AppendCollections iSkipOnNil
   784  func (it *LinkedCollections) AppendCollections(
   785  	isSkipOnNull bool,
   786  	collections ...*Collection,
   787  ) *LinkedCollections {
   788  	if isSkipOnNull && collections == nil {
   789  		return it
   790  	}
   791  
   792  	for i := range collections {
   793  		collection := collections[i]
   794  		if isSkipOnNull && collection == nil {
   795  			continue
   796  		}
   797  
   798  		it.Add(collection)
   799  	}
   800  
   801  	return it
   802  }
   803  
   804  // AppendCollectionsPointersLock iSkipOnNil
   805  func (it *LinkedCollections) AppendCollectionsPointersLock(
   806  	isSkipOnNull bool,
   807  	collections *[]*Collection,
   808  ) *LinkedCollections {
   809  	if isSkipOnNull && collections == nil {
   810  		return it
   811  	}
   812  
   813  	for i := range *collections {
   814  		collection := (*collections)[i]
   815  		if isSkipOnNull && collection == nil {
   816  			continue
   817  		}
   818  
   819  		it.AddLock(collection)
   820  	}
   821  
   822  	return it
   823  }
   824  
   825  // AppendCollectionsPointers iSkipOnNil
   826  func (it *LinkedCollections) AppendCollectionsPointers(
   827  	isSkipOnNull bool,
   828  	collections *[]*Collection,
   829  ) *LinkedCollections {
   830  	if isSkipOnNull && collections == nil {
   831  		return it
   832  	}
   833  
   834  	for i := range *collections {
   835  		collection := (*collections)[i]
   836  		if isSkipOnNull && collection == nil {
   837  			continue
   838  		}
   839  
   840  		it.Add(collection)
   841  	}
   842  
   843  	return it
   844  }
   845  
   846  // AddCollectionsToNodeAsync iSkipOnNil
   847  func (it *LinkedCollections) AddCollectionsToNodeAsync(
   848  	isSkipOnNull bool,
   849  	wg *sync.WaitGroup,
   850  	node *LinkedCollectionNode,
   851  	collections ...*Collection,
   852  ) *LinkedCollections {
   853  	if isSkipOnNull && collections == nil {
   854  		return it
   855  	}
   856  
   857  	go func() {
   858  		it.Lock()
   859  		it.AddCollectionsPointerToNode(
   860  			isSkipOnNull,
   861  			node,
   862  			&collections)
   863  
   864  		it.Unlock()
   865  
   866  		wg.Done()
   867  	}()
   868  
   869  	return it
   870  }
   871  
   872  // AddCollectionsToNode iSkipOnNil
   873  func (it *LinkedCollections) AddCollectionsToNode(
   874  	isSkipOnNull bool,
   875  	node *LinkedCollectionNode,
   876  	collections ...*Collection,
   877  ) *LinkedCollections {
   878  	if isSkipOnNull && collections == nil {
   879  		return it
   880  	}
   881  
   882  	return it.AddCollectionsPointerToNode(
   883  		isSkipOnNull,
   884  		node,
   885  		&collections)
   886  }
   887  
   888  // AddCollectionsPointerToNode iSkipOnNil
   889  func (it *LinkedCollections) AddCollectionsPointerToNode(
   890  	isSkipOnNull bool,
   891  	node *LinkedCollectionNode,
   892  	items *[]*Collection,
   893  ) *LinkedCollections {
   894  	if items == nil || node == nil && isSkipOnNull {
   895  		return it
   896  	}
   897  
   898  	if node == nil {
   899  		errcore.
   900  			CannotBeNilType.
   901  			HandleUsingPanic(
   902  				nodesCannotBeNull,
   903  				nil)
   904  	}
   905  
   906  	length := len(*items)
   907  
   908  	if length == 0 {
   909  		return it
   910  	}
   911  
   912  	if length == 1 {
   913  		it.AddAfterNode(node, (*items)[0])
   914  
   915  		return it
   916  	}
   917  
   918  	finalHead := &LinkedCollectionNode{
   919  		Element: (*items)[0],
   920  		next:    nil,
   921  	}
   922  
   923  	nextNode := finalHead
   924  
   925  	for _, collection := range (*items)[1:] {
   926  		if isSkipOnNull && collection == nil {
   927  			continue
   928  		}
   929  
   930  		nextNode = nextNode.AddNext(it, collection)
   931  	}
   932  
   933  	//goland:noinspection GoNilness
   934  	nextNode.next = node.next
   935  	//goland:noinspection GoNilness
   936  	node.next = finalHead
   937  	it.incrementLength()
   938  
   939  	return it
   940  }
   941  
   942  func (it *LinkedCollections) AddAfterNode(
   943  	node *LinkedCollectionNode,
   944  	collection *Collection,
   945  ) *LinkedCollectionNode {
   946  	newNode := &LinkedCollectionNode{
   947  		Element: collection,
   948  		next:    node.next,
   949  	}
   950  
   951  	node.next = newNode
   952  	it.incrementLength()
   953  
   954  	return newNode
   955  }
   956  
   957  func (it *LinkedCollections) AddAfterNodeAsync(
   958  	wg *sync.WaitGroup,
   959  	node *LinkedCollectionNode,
   960  	collection *Collection,
   961  ) {
   962  	go func() {
   963  		it.Lock()
   964  
   965  		it.AddAfterNode(node, collection)
   966  
   967  		it.Unlock()
   968  
   969  		wg.Done()
   970  	}()
   971  }
   972  
   973  // AddStringsPtrAsync add to back
   974  func (it *LinkedCollections) AddStringsPtrAsync(
   975  	wg *sync.WaitGroup,
   976  	isMakeClone bool,
   977  	items *[]string,
   978  ) *LinkedCollections {
   979  	if items == nil {
   980  		return it
   981  	}
   982  
   983  	go func() {
   984  		collection := New.Collection.StringsPtrOption(isMakeClone, items)
   985  
   986  		it.Lock()
   987  
   988  		it.Add(collection)
   989  
   990  		it.Unlock()
   991  
   992  		wg.Done()
   993  	}()
   994  
   995  	return it
   996  }
   997  
   998  func (it *LinkedCollections) ConcatNew(
   999  	isMakeCloneOnEmpty bool,
  1000  	linkedCollectionsOfCollection ...*LinkedCollections,
  1001  ) *LinkedCollections {
  1002  	isEmpty := len(linkedCollectionsOfCollection) == 0
  1003  
  1004  	if isEmpty && isMakeCloneOnEmpty {
  1005  		return New.
  1006  			LinkedCollection.
  1007  			Create().
  1008  			AddAnother(it)
  1009  	} else if isEmpty && !isMakeCloneOnEmpty {
  1010  		return it
  1011  	}
  1012  
  1013  	newLinkedCollections := New.
  1014  		LinkedCollection.
  1015  		Create()
  1016  	newLinkedCollections.AddAnother(it)
  1017  
  1018  	for _, linkedCollection := range linkedCollectionsOfCollection {
  1019  		newLinkedCollections.AddAnother(linkedCollection)
  1020  	}
  1021  
  1022  	return newLinkedCollections
  1023  }
  1024  
  1025  // AddAsyncFuncItems must add all the lengths to the wg
  1026  func (it *LinkedCollections) AddAsyncFuncItems(
  1027  	wg *sync.WaitGroup,
  1028  	isMakeClone bool,
  1029  	asyncFunctions ...func() []string,
  1030  ) *LinkedCollections {
  1031  	if asyncFunctions == nil {
  1032  		return it
  1033  	}
  1034  
  1035  	asyncFuncWrap := func(asyncFunc func() []string) {
  1036  		items := asyncFunc()
  1037  
  1038  		if len(items) == 0 {
  1039  			wg.Done()
  1040  
  1041  			return
  1042  		}
  1043  
  1044  		collection := New.Collection.StringsOptions(isMakeClone, items)
  1045  
  1046  		it.Lock()
  1047  		it.Add(collection)
  1048  		it.Unlock()
  1049  
  1050  		wg.Done()
  1051  	}
  1052  
  1053  	for _, function := range asyncFunctions {
  1054  		go asyncFuncWrap(function)
  1055  	}
  1056  
  1057  	wg.Wait()
  1058  
  1059  	return it
  1060  }
  1061  
  1062  // AddAsyncFuncItemsPointer must add all the lengths to the wg
  1063  func (it *LinkedCollections) AddAsyncFuncItemsPointer(
  1064  	wg *sync.WaitGroup,
  1065  	isMakeClone bool,
  1066  	asyncFunctions ...func() *[]string,
  1067  ) *LinkedCollections {
  1068  	if asyncFunctions == nil {
  1069  		return it
  1070  	}
  1071  
  1072  	asyncFuncWrap := func(asyncFunc func() *[]string) {
  1073  		items := asyncFunc()
  1074  
  1075  		if items == nil || len(*items) == 0 {
  1076  			wg.Done()
  1077  
  1078  			return
  1079  		}
  1080  
  1081  		collection := New.Collection.StringsPtrOption(isMakeClone, items)
  1082  
  1083  		it.Lock()
  1084  		it.Add(collection)
  1085  		it.Unlock()
  1086  
  1087  		wg.Done()
  1088  	}
  1089  
  1090  	for _, function := range asyncFunctions {
  1091  		go asyncFuncWrap(function)
  1092  	}
  1093  
  1094  	wg.Wait()
  1095  
  1096  	return it
  1097  }
  1098  
  1099  // AddStringsPtr add to back
  1100  func (it *LinkedCollections) AddStringsPtr(
  1101  	isMakeClone bool,
  1102  	items *[]string,
  1103  ) *LinkedCollections {
  1104  	if items == nil {
  1105  		return it
  1106  	}
  1107  
  1108  	collection := New.Collection.StringsPtrOption(isMakeClone, items)
  1109  
  1110  	return it.Add(collection)
  1111  }
  1112  
  1113  // AddStringsOfStringsPtr add to back
  1114  func (it *LinkedCollections) AddStringsOfStringsPtr(
  1115  	items *[]*[]string,
  1116  	isMakeClone bool,
  1117  ) *LinkedCollections {
  1118  	if items == nil || len(*items) == 0 {
  1119  		return it
  1120  	}
  1121  
  1122  	for _, stringItems := range *items {
  1123  		if stringItems == nil {
  1124  			continue
  1125  		}
  1126  
  1127  		it.AddStringsPtr(
  1128  			isMakeClone,
  1129  			stringItems,
  1130  		)
  1131  	}
  1132  
  1133  	return it
  1134  }
  1135  
  1136  // IndexAt Expensive operation BigO(n)
  1137  func (it *LinkedCollections) IndexAt(
  1138  	index int,
  1139  ) *LinkedCollectionNode {
  1140  	length := it.Length()
  1141  	if index < 0 {
  1142  		return nil
  1143  	}
  1144  
  1145  	if length == 0 || length-1 < index {
  1146  		errcore.OutOfRangeType.HandleUsingPanic(
  1147  			"Given index is out of range. Whereas length:",
  1148  			length)
  1149  	}
  1150  
  1151  	if index == 0 {
  1152  		return it.head
  1153  	}
  1154  
  1155  	node := it.head
  1156  	i := 1
  1157  	for node.HasNext() {
  1158  		node = node.Next()
  1159  
  1160  		if i == index {
  1161  			return node
  1162  		}
  1163  
  1164  		i++
  1165  	}
  1166  
  1167  	return nil
  1168  }
  1169  
  1170  // SafePointerIndexAt Expensive operation BigO(n)
  1171  func (it *LinkedCollections) SafePointerIndexAt(
  1172  	index int,
  1173  ) *Collection {
  1174  	node := it.SafeIndexAt(index)
  1175  
  1176  	if node == nil {
  1177  		return nil
  1178  	}
  1179  
  1180  	return node.Element
  1181  }
  1182  
  1183  // SafeIndexAt Expensive operation BigO(n)
  1184  func (it *LinkedCollections) SafeIndexAt(
  1185  	index int,
  1186  ) *LinkedCollectionNode {
  1187  	length := it.Length()
  1188  	isExitCondition := index < 0 || length == 0 || length-1 < index
  1189  	if isExitCondition {
  1190  		return nil
  1191  	}
  1192  
  1193  	if index == 0 {
  1194  		return it.head
  1195  	}
  1196  
  1197  	node := it.head
  1198  	i := 1
  1199  	for node.HasNext() {
  1200  		node = node.Next()
  1201  
  1202  		if i == index {
  1203  			return node
  1204  		}
  1205  
  1206  		i++
  1207  	}
  1208  
  1209  	return nil
  1210  }
  1211  
  1212  // AddPointerStringsPtr skip on nil, add to back
  1213  func (it *LinkedCollections) AddPointerStringsPtr(
  1214  	items *[]*string,
  1215  ) *LinkedCollections {
  1216  	if items == nil {
  1217  		return it
  1218  	}
  1219  
  1220  	collection := New.Collection.PointerStrings(*items)
  1221  
  1222  	return it.Add(collection)
  1223  }
  1224  
  1225  // AddPointerStringsPtrAsync skip on nil, add to back
  1226  func (it *LinkedCollections) AddPointerStringsPtrAsync(
  1227  	wg *sync.WaitGroup,
  1228  	items *[]*string,
  1229  ) *LinkedCollections {
  1230  	if items == nil {
  1231  		return it
  1232  	}
  1233  
  1234  	go func() {
  1235  		collection := New.Collection.PointerStrings(*items)
  1236  
  1237  		it.Lock()
  1238  		it.Add(collection)
  1239  		it.Unlock()
  1240  
  1241  		wg.Done()
  1242  	}()
  1243  
  1244  	return it
  1245  }
  1246  
  1247  // AddCollection skip on nil
  1248  func (it *LinkedCollections) AddCollection(
  1249  	collection *Collection,
  1250  ) *LinkedCollections {
  1251  	if collection == nil {
  1252  		return it
  1253  	}
  1254  
  1255  	return it.Add(collection)
  1256  }
  1257  
  1258  // AddCollectionsPtr skip on nil
  1259  func (it *LinkedCollections) AddCollectionsPtr(
  1260  	collectionsOfCollection *[]*Collection,
  1261  ) *LinkedCollections {
  1262  	if collectionsOfCollection == nil || len(*collectionsOfCollection) == 0 {
  1263  		return it
  1264  	}
  1265  
  1266  	return it.AddCollections(*collectionsOfCollection)
  1267  }
  1268  
  1269  // AddCollections skip on nil
  1270  func (it *LinkedCollections) AddCollections(
  1271  	collectionsOfCollection []*Collection,
  1272  ) *LinkedCollections {
  1273  	if len(collectionsOfCollection) == 0 {
  1274  		return it
  1275  	}
  1276  
  1277  	for _, collection := range collectionsOfCollection {
  1278  		if collection == nil {
  1279  			continue
  1280  		}
  1281  
  1282  		return it.Add(collection)
  1283  	}
  1284  
  1285  	return it
  1286  }
  1287  
  1288  func (it *LinkedCollections) ToStringsPtr() *[]string {
  1289  	return it.ToCollectionSimple().ListPtr()
  1290  }
  1291  
  1292  func (it *LinkedCollections) ToStrings() []string {
  1293  	return it.ToCollectionSimple().List()
  1294  }
  1295  
  1296  func (it *LinkedCollections) ToCollectionSimple() *Collection {
  1297  	return it.ToCollection(constants.Zero)
  1298  }
  1299  
  1300  func (it *LinkedCollections) ToCollection(
  1301  	addCapacity int,
  1302  ) *Collection {
  1303  	if it.IsEmpty() {
  1304  		return New.Collection.Empty()
  1305  	}
  1306  
  1307  	newLength := it.AllIndividualItemsLength() +
  1308  		addCapacity
  1309  
  1310  	collection := New.Collection.Cap(newLength)
  1311  	var processor LinkedCollectionSimpleProcessor = func(
  1312  		arg *LinkedCollectionProcessorParameter,
  1313  	) (isBreak bool) {
  1314  		if arg.CurrentNode == nil {
  1315  			return false
  1316  		}
  1317  
  1318  		collection.AddCollection(arg.CurrentNode.Element)
  1319  
  1320  		return false
  1321  	}
  1322  
  1323  	it.Loop(processor)
  1324  
  1325  	return collection
  1326  }
  1327  
  1328  func (it *LinkedCollections) ToCollectionsOfCollection(
  1329  	addCapacity int,
  1330  ) *CollectionsOfCollection {
  1331  	if it.IsEmpty() {
  1332  		return Empty.CollectionsOfCollection()
  1333  	}
  1334  
  1335  	newLength := it.AllIndividualItemsLength() +
  1336  		addCapacity
  1337  
  1338  	collection := New.CollectionsOfCollection.Cap(newLength)
  1339  
  1340  	var processor LinkedCollectionSimpleProcessor = func(
  1341  		arg *LinkedCollectionProcessorParameter,
  1342  	) (isBreak bool) {
  1343  		if arg.CurrentNode == nil {
  1344  			return false
  1345  		}
  1346  
  1347  		collection.Adds(arg.CurrentNode.Element)
  1348  
  1349  		return false
  1350  	}
  1351  
  1352  	it.Loop(processor)
  1353  
  1354  	return collection
  1355  }
  1356  
  1357  func (it *LinkedCollections) ItemsOfItems() *[]*[]string {
  1358  	length := it.Length()
  1359  	itemsOfItems := make([]*[]string, length)
  1360  
  1361  	if length == 0 {
  1362  		return &itemsOfItems
  1363  	}
  1364  
  1365  	nodes := it.GetAllLinkedNodes()
  1366  
  1367  	for i, node := range *nodes {
  1368  		itemsOfItems[i] = &node.Element.items
  1369  	}
  1370  
  1371  	return &itemsOfItems
  1372  }
  1373  
  1374  func (it *LinkedCollections) ItemsOfItemsCollection() *[]*Collection {
  1375  	length := it.Length()
  1376  	itemsOfItems := make([]*Collection, length)
  1377  
  1378  	if length == 0 {
  1379  		return &itemsOfItems
  1380  	}
  1381  
  1382  	nodes := it.GetAllLinkedNodes()
  1383  
  1384  	for i, node := range *nodes {
  1385  		itemsOfItems[i] = node.Element
  1386  	}
  1387  
  1388  	return &itemsOfItems
  1389  }
  1390  
  1391  // ListPtr must return slice.
  1392  func (it *LinkedCollections) ListPtr() *[]string {
  1393  	return it.
  1394  		ToCollection(constants.ArbitraryCapacity5).
  1395  		ListPtr()
  1396  }
  1397  
  1398  func (it *LinkedCollections) String() string {
  1399  	if it.IsEmpty() {
  1400  		return commonJoiner + NoElements
  1401  	}
  1402  
  1403  	collections := *it.ToCollectionsOfCollection(0)
  1404  
  1405  	return collections.String()
  1406  }
  1407  
  1408  func (it *LinkedCollections) StringLock() string {
  1409  	if it.IsEmptyLock() {
  1410  		return commonJoiner + NoElements
  1411  	}
  1412  
  1413  	it.Lock()
  1414  	defer it.Unlock()
  1415  
  1416  	return commonJoiner +
  1417  		strings.Join(
  1418  			*it.ListPtr(),
  1419  			commonJoiner)
  1420  }
  1421  
  1422  func (it *LinkedCollections) Join(
  1423  	separator string,
  1424  ) string {
  1425  	return strings.Join(*it.ListPtr(), separator)
  1426  }
  1427  
  1428  func (it *LinkedCollections) Joins(
  1429  	separator string,
  1430  	items ...string,
  1431  ) string {
  1432  	if items == nil || it.Length() == 0 {
  1433  		return strings.Join(items, separator)
  1434  	}
  1435  
  1436  	collection := it.ToCollection(len(items) +
  1437  		constants.ArbitraryCapacity2)
  1438  	collection.AddStringsPtr(&items)
  1439  
  1440  	return collection.Join(separator)
  1441  }
  1442  
  1443  func (it *LinkedCollections) JsonModel() []string {
  1444  	return it.ToCollection(0).JsonModel()
  1445  }
  1446  
  1447  func (it *LinkedCollections) JsonModelAny() interface{} {
  1448  	return it.JsonModel()
  1449  }
  1450  
  1451  func (it *LinkedCollections) MarshalJSON() ([]byte, error) {
  1452  	return json.Marshal(it.JsonModel())
  1453  }
  1454  
  1455  func (it *LinkedCollections) UnmarshalJSON(data []byte) error {
  1456  	var dataModelStrings []string
  1457  	err := json.Unmarshal(data, &dataModelStrings)
  1458  
  1459  	if err == nil {
  1460  		it.Clear()
  1461  		it.AddStrings(dataModelStrings...)
  1462  	}
  1463  
  1464  	return err
  1465  }
  1466  
  1467  func (it *LinkedCollections) RemoveAll() *LinkedCollections {
  1468  	return it.Clear()
  1469  }
  1470  
  1471  func (it *LinkedCollections) Clear() *LinkedCollections {
  1472  	if it.IsEmpty() {
  1473  		return it
  1474  	}
  1475  
  1476  	it.head = nil
  1477  	it.tail = nil
  1478  	it.setLengthToZero()
  1479  
  1480  	return it
  1481  }
  1482  
  1483  func (it LinkedCollections) Json() corejson.Result {
  1484  	return corejson.New(it)
  1485  }
  1486  
  1487  func (it LinkedCollections) JsonPtr() *corejson.Result {
  1488  	return corejson.NewPtr(it)
  1489  }
  1490  
  1491  func (it *LinkedCollections) ParseInjectUsingJson(
  1492  	jsonResult *corejson.Result,
  1493  ) (*LinkedCollections, error) {
  1494  	err := jsonResult.Unmarshal(it)
  1495  
  1496  	if err != nil {
  1497  		return nil, err
  1498  	}
  1499  
  1500  	return it, nil
  1501  }
  1502  
  1503  // ParseInjectUsingJsonMust Panic if error
  1504  func (it *LinkedCollections) ParseInjectUsingJsonMust(
  1505  	jsonResult *corejson.Result,
  1506  ) *LinkedCollections {
  1507  	newUsingJson, err :=
  1508  		it.ParseInjectUsingJson(jsonResult)
  1509  
  1510  	if err != nil {
  1511  		panic(err)
  1512  	}
  1513  
  1514  	return newUsingJson
  1515  }
  1516  
  1517  func (it *LinkedCollections) GetCompareSummary(
  1518  	right *LinkedCollections, leftName, rightName string,
  1519  ) string {
  1520  	lLen := it.Length()
  1521  	rLen := right.Length()
  1522  
  1523  	leftStr := fmt.Sprintf(
  1524  		linkedListCollectionCompareHeaderLeft,
  1525  		leftName,
  1526  		lLen,
  1527  		it)
  1528  
  1529  	rightStr := fmt.Sprintf(
  1530  		linkedListCollectionCompareHeaderRight,
  1531  		rightName,
  1532  		rLen,
  1533  		right,
  1534  		it.IsEqualsPtr(right),
  1535  		lLen,
  1536  		rLen)
  1537  
  1538  	return leftStr + rightStr
  1539  }
  1540  
  1541  func (it *LinkedCollections) JsonParseSelfInject(
  1542  	jsonResult *corejson.Result,
  1543  ) error {
  1544  	_, err := it.ParseInjectUsingJson(
  1545  		jsonResult,
  1546  	)
  1547  
  1548  	return err
  1549  }
  1550  
  1551  func (it *LinkedCollections) AsJsonContractsBinder() corejson.JsonContractsBinder {
  1552  	return it
  1553  }
  1554  
  1555  func (it *LinkedCollections) AsJsoner() corejson.Jsoner {
  1556  	return it
  1557  }
  1558  
  1559  func (it *LinkedCollections) AsJsonParseSelfInjector() corejson.JsonParseSelfInjector {
  1560  	return it
  1561  }
  1562  
  1563  func (it *LinkedCollections) AsJsonMarshaller() corejson.JsonMarshaller {
  1564  	return it
  1565  }