@@ -17,8 +17,8 @@ internal abstract class ContentNavigationServiceBase<TContentType, TContentTypeS
17
17
private Lazy < Dictionary < string , Guid > > _contentTypeAliasToKeyMap ;
18
18
private ConcurrentDictionary < Guid , NavigationNode > _navigationStructure = new ( ) ;
19
19
private ConcurrentDictionary < Guid , NavigationNode > _recycleBinNavigationStructure = new ( ) ;
20
- private IList < Guid > _roots = new List < Guid > ( ) ;
21
- private IList < Guid > _recycleBinRoots = new List < Guid > ( ) ;
20
+ private HashSet < Guid > _roots = [ ] ;
21
+ private HashSet < Guid > _recycleBinRoots = [ ] ;
22
22
23
23
protected ContentNavigationServiceBase ( ICoreScopeProvider coreScopeProvider , INavigationRepository navigationRepository , TContentTypeService typeService )
24
24
{
@@ -321,7 +321,7 @@ protected Task HandleRebuildAsync(int readLock, Guid objectTypeKey, bool trashed
321
321
return Task . CompletedTask ;
322
322
}
323
323
324
- private bool TryGetParentKeyFromStructure ( ConcurrentDictionary < Guid , NavigationNode > structure , Guid childKey , out Guid ? parentKey )
324
+ private static bool TryGetParentKeyFromStructure ( ConcurrentDictionary < Guid , NavigationNode > structure , Guid childKey , out Guid ? parentKey )
325
325
{
326
326
if ( structure . TryGetValue ( childKey , out NavigationNode ? childNode ) )
327
327
{
@@ -335,25 +335,32 @@ private bool TryGetParentKeyFromStructure(ConcurrentDictionary<Guid, NavigationN
335
335
}
336
336
337
337
private bool TryGetRootKeysFromStructure (
338
- IList < Guid > input ,
338
+ HashSet < Guid > input ,
339
339
out IEnumerable < Guid > rootKeys ,
340
340
Guid ? contentTypeKey = null )
341
341
{
342
- // Apply contentTypeKey filter
343
- IEnumerable < Guid > filteredKeys = contentTypeKey . HasValue
344
- ? input . Where ( key => _navigationStructure [ key ] . ContentTypeKey == contentTypeKey . Value )
345
- : input ;
342
+ var keysWithSortOrder = new List < ( Guid Key , int SortOrder ) > ( input . Count ) ;
343
+ foreach ( Guid key in input )
344
+ {
345
+ NavigationNode navigationNode = _navigationStructure [ key ] ;
346
+
347
+ // Apply contentTypeKey filter
348
+ if ( contentTypeKey . HasValue && navigationNode . ContentTypeKey != contentTypeKey . Value )
349
+ {
350
+ continue ;
351
+ }
352
+
353
+ keysWithSortOrder . Add ( ( key , navigationNode . SortOrder ) ) ;
354
+ }
346
355
347
- // TODO can we make this more efficient?
348
356
// Sort by SortOrder
349
- rootKeys = filteredKeys
350
- . OrderBy ( key => _navigationStructure [ key ] . SortOrder )
351
- . ToList ( ) ;
357
+ keysWithSortOrder . Sort ( ( a , b ) => a . SortOrder . CompareTo ( b . SortOrder ) ) ;
358
+ rootKeys = keysWithSortOrder . ConvertAll ( keyWithSortOrder => keyWithSortOrder . Key ) ;
352
359
353
360
return true ;
354
361
}
355
362
356
- private bool TryGetChildrenKeysFromStructure (
363
+ private static bool TryGetChildrenKeysFromStructure (
357
364
ConcurrentDictionary < Guid , NavigationNode > structure ,
358
365
Guid parentKey ,
359
366
out IEnumerable < Guid > childrenKeys ,
@@ -367,12 +374,12 @@ private bool TryGetChildrenKeysFromStructure(
367
374
}
368
375
369
376
// Keep children keys ordered based on their SortOrder
370
- childrenKeys = GetOrderedChildren ( parentNode , structure , contentTypeKey ) . ToList ( ) ;
377
+ childrenKeys = GetOrderedChildren ( parentNode , structure , contentTypeKey ) ;
371
378
372
379
return true ;
373
380
}
374
381
375
- private bool TryGetDescendantsKeysFromStructure (
382
+ private static bool TryGetDescendantsKeysFromStructure (
376
383
ConcurrentDictionary < Guid , NavigationNode > structure ,
377
384
Guid parentKey ,
378
385
out IEnumerable < Guid > descendantsKeys ,
@@ -393,7 +400,7 @@ private bool TryGetDescendantsKeysFromStructure(
393
400
return true ;
394
401
}
395
402
396
- private bool TryGetAncestorsKeysFromStructure (
403
+ private static bool TryGetAncestorsKeysFromStructure (
397
404
ConcurrentDictionary < Guid , NavigationNode > structure ,
398
405
Guid childKey ,
399
406
out IEnumerable < Guid > ancestorsKeys ,
@@ -421,7 +428,7 @@ private bool TryGetAncestorsKeysFromStructure(
421
428
return true ;
422
429
}
423
430
424
- private bool TryGetSiblingsKeysFromStructure (
431
+ private static bool TryGetSiblingsKeysFromStructure (
425
432
ConcurrentDictionary < Guid , NavigationNode > structure ,
426
433
Guid key ,
427
434
out IEnumerable < Guid > siblingsKeys ,
@@ -463,14 +470,14 @@ private bool TryGetSiblingsKeysFromStructure(
463
470
return true ;
464
471
}
465
472
466
- private void GetDescendantsRecursively (
473
+ private static void GetDescendantsRecursively (
467
474
ConcurrentDictionary < Guid , NavigationNode > structure ,
468
475
NavigationNode node ,
469
476
List < Guid > descendants ,
470
477
Guid ? contentTypeKey = null )
471
478
{
472
479
// Get all children regardless of contentType
473
- var childrenKeys = GetOrderedChildren ( node , structure ) . ToList ( ) ;
480
+ IReadOnlyList < Guid > childrenKeys = GetOrderedChildren ( node , structure ) ;
474
481
foreach ( Guid childKey in childrenKeys )
475
482
{
476
483
// Apply contentTypeKey filter
@@ -487,7 +494,7 @@ private void GetDescendantsRecursively(
487
494
}
488
495
}
489
496
490
- private bool TryRemoveNodeFromParentInStructure ( ConcurrentDictionary < Guid , NavigationNode > structure , Guid key , out NavigationNode ? nodeToRemove )
497
+ private static bool TryRemoveNodeFromParentInStructure ( ConcurrentDictionary < Guid , NavigationNode > structure , Guid key , out NavigationNode ? nodeToRemove )
491
498
{
492
499
if ( structure . TryGetValue ( key , out nodeToRemove ) is false )
493
500
{
@@ -507,7 +514,7 @@ private void AddDescendantsToRecycleBinRecursively(NavigationNode node)
507
514
{
508
515
_recycleBinRoots . Add ( node . Key ) ;
509
516
_roots . Remove ( node . Key ) ;
510
- var childrenKeys = GetOrderedChildren ( node , _navigationStructure ) . ToList ( ) ;
517
+ IReadOnlyList < Guid > childrenKeys = GetOrderedChildren ( node , _navigationStructure ) ;
511
518
512
519
foreach ( Guid childKey in childrenKeys )
513
520
{
@@ -530,7 +537,7 @@ private void AddDescendantsToRecycleBinRecursively(NavigationNode node)
530
537
531
538
private void RemoveDescendantsRecursively ( NavigationNode node )
532
539
{
533
- var childrenKeys = GetOrderedChildren ( node , _recycleBinNavigationStructure ) . ToList ( ) ;
540
+ IReadOnlyList < Guid > childrenKeys = GetOrderedChildren ( node , _recycleBinNavigationStructure ) ;
534
541
foreach ( Guid childKey in childrenKeys )
535
542
{
536
543
if ( _recycleBinNavigationStructure . TryGetValue ( childKey , out NavigationNode ? childNode ) is false )
@@ -551,7 +558,7 @@ private void RestoreNodeAndDescendantsRecursively(NavigationNode node)
551
558
}
552
559
553
560
_recycleBinRoots . Remove ( node . Key ) ;
554
- var childrenKeys = GetOrderedChildren ( node , _recycleBinNavigationStructure ) . ToList ( ) ;
561
+ IReadOnlyList < Guid > childrenKeys = GetOrderedChildren ( node , _recycleBinNavigationStructure ) ;
555
562
556
563
foreach ( Guid childKey in childrenKeys )
557
564
{
@@ -570,24 +577,35 @@ private void RestoreNodeAndDescendantsRecursively(NavigationNode node)
570
577
}
571
578
}
572
579
573
- private IEnumerable < Guid > GetOrderedChildren (
580
+ private static IReadOnlyList < Guid > GetOrderedChildren (
574
581
NavigationNode node ,
575
582
ConcurrentDictionary < Guid , NavigationNode > structure ,
576
583
Guid ? contentTypeKey = null )
577
584
{
578
- IEnumerable < Guid > children = node
579
- . Children
580
- . Where ( structure . ContainsKey ) ;
585
+ if ( node . Children . Count < 1 )
586
+ {
587
+ return [ ] ;
588
+ }
581
589
582
- // Apply contentTypeKey filter
583
- if ( contentTypeKey . HasValue )
590
+ var childrenWithSortOrder = new List < ( Guid ChildNodeKey , int SortOrder ) > ( node . Children . Count ) ;
591
+ foreach ( Guid childNodeKey in node . Children )
584
592
{
585
- children = children . Where ( childKey => structure [ childKey ] . ContentTypeKey == contentTypeKey . Value ) ;
593
+ if ( ! structure . TryGetValue ( childNodeKey , out NavigationNode ? childNode ) )
594
+ {
595
+ continue ;
596
+ }
597
+
598
+ // Apply contentTypeKey filter
599
+ if ( contentTypeKey . HasValue && childNode . ContentTypeKey != contentTypeKey . Value )
600
+ {
601
+ continue ;
602
+ }
603
+
604
+ childrenWithSortOrder . Add ( ( childNodeKey , childNode . SortOrder ) ) ;
586
605
}
587
606
588
- return children
589
- . OrderBy ( childKey => structure [ childKey ] . SortOrder )
590
- . ToList ( ) ;
607
+ childrenWithSortOrder . Sort ( ( a , b ) => a . SortOrder . CompareTo ( b . SortOrder ) ) ;
608
+ return childrenWithSortOrder . ConvertAll ( childWithSortOrder => childWithSortOrder . ChildNodeKey ) ;
591
609
}
592
610
593
611
private bool TryGetContentTypeKey ( string contentTypeAlias , out Guid ? contentTypeKey )
@@ -613,7 +631,7 @@ private bool TryGetContentTypeKey(string contentTypeAlias, out Guid? contentType
613
631
return true ;
614
632
}
615
633
616
- private static void BuildNavigationDictionary ( ConcurrentDictionary < Guid , NavigationNode > nodesStructure , IList < Guid > roots , IEnumerable < INavigationModel > entities )
634
+ private static void BuildNavigationDictionary ( ConcurrentDictionary < Guid , NavigationNode > nodesStructure , HashSet < Guid > roots , IEnumerable < INavigationModel > entities )
617
635
{
618
636
var entityList = entities . ToList ( ) ;
619
637
var idToKeyMap = entityList . ToDictionary ( x => x . Id , x => x . Key ) ;
0 commit comments