@@ -9,6 +9,9 @@ namespace SimpleIdServer.Scim.Domains
99{
1010 public class SCIMRepresentation : BaseDomain , IEquatable < SCIMRepresentation >
1111 {
12+ private Dictionary < string , SCIMSchema > _schemaByAttributeIdCache ;
13+ private Dictionary < string , SCIMSchema > _schemaByIdCache ;
14+
1215 public SCIMRepresentation ( )
1316 {
1417 Schemas = new List < SCIMSchema > ( ) ;
@@ -81,12 +84,65 @@ public SCIMSchema GetSchema(SCIMRepresentationAttribute attribute)
8184
8285 public SCIMSchema GetSchema ( SCIMSchemaAttribute attribute )
8386 {
84- return Schemas . FirstOrDefault ( s => s . HasAttribute ( attribute ) ) ;
87+ EnsureSchemaCacheInitialized ( ) ;
88+
89+ if ( _schemaByAttributeIdCache . TryGetValue ( attribute . Id , out var schema ) )
90+ {
91+ return schema ;
92+ }
93+
94+ return null ;
8595 }
8696
8797 public SCIMSchema GetSchema ( string id )
8898 {
89- return Schemas . FirstOrDefault ( s => s . Id == id ) ;
99+ EnsureSchemaCacheInitialized ( ) ;
100+
101+ if ( _schemaByIdCache . TryGetValue ( id , out var schema ) )
102+ {
103+ return schema ;
104+ }
105+
106+ return null ;
107+ }
108+
109+ public SCIMSchema GetSchemaByAttributeId ( string attributeId )
110+ {
111+ EnsureSchemaCacheInitialized ( ) ;
112+
113+ if ( _schemaByAttributeIdCache . TryGetValue ( attributeId , out var schema ) )
114+ {
115+ return schema ;
116+ }
117+
118+ return null ;
119+ }
120+
121+ private void EnsureSchemaCacheInitialized ( )
122+ {
123+ if ( _schemaByAttributeIdCache != null && _schemaByIdCache != null )
124+ {
125+ return ;
126+ }
127+
128+ _schemaByAttributeIdCache = new Dictionary < string , SCIMSchema > ( ) ;
129+ _schemaByIdCache = new Dictionary < string , SCIMSchema > ( ) ;
130+
131+ foreach ( var schema in Schemas )
132+ {
133+ _schemaByIdCache [ schema . Id ] = schema ;
134+
135+ foreach ( var attribute in schema . Attributes )
136+ {
137+ _schemaByAttributeIdCache [ attribute . Id ] = schema ;
138+ }
139+ }
140+ }
141+
142+ public void InvalidateSchemaCache ( )
143+ {
144+ _schemaByAttributeIdCache = null ;
145+ _schemaByIdCache = null ;
90146 }
91147
92148 public void AddAttribute ( SCIMRepresentationAttribute attribute )
@@ -384,37 +440,71 @@ public static List<SCIMRepresentationAttribute> BuildFlatAttributes(ICollection<
384440 public static List < SCIMRepresentationAttribute > BuildHierarchicalAttributes ( IEnumerable < SCIMRepresentationAttribute > attributes )
385441 {
386442 var rootId = string . Empty ;
387- if ( attributes . Count ( ) == 0 ) return new List < SCIMRepresentationAttribute > ( ) ;
443+ var attributesList = attributes as List < SCIMRepresentationAttribute > ?? attributes . ToList ( ) ;
444+ if ( attributesList . Count == 0 ) return new List < SCIMRepresentationAttribute > ( ) ;
445+
388446 var parentsDictionary = new Dictionary < string , List < SCIMRepresentationAttribute > > ( ) ;
389- var treeNodes = new List < SCIMRepresentationAttribute > ( ) ;
390- foreach ( var scimRepresentationAttribute in attributes )
447+ var existingIds = new HashSet < string > ( attributesList . Count ) ;
448+ var emptyList = new List < SCIMRepresentationAttribute > ( ) ;
449+
450+ foreach ( var attr in attributesList )
391451 {
392- var parentIdKey = scimRepresentationAttribute . ParentAttributeId ?? rootId ;
393- treeNodes . Add ( scimRepresentationAttribute ) ;
394- if ( ! parentsDictionary . ContainsKey ( parentIdKey ) )
452+ existingIds . Add ( attr . Id ) ;
453+ var parentIdKey = attr . ParentAttributeId ?? rootId ;
454+ if ( ! parentsDictionary . TryGetValue ( parentIdKey , out var children ) )
395455 {
396- parentsDictionary [ parentIdKey ] = new List < SCIMRepresentationAttribute > ( ) { scimRepresentationAttribute } ;
397- continue ;
456+ children = new List < SCIMRepresentationAttribute > ( ) ;
457+ parentsDictionary [ parentIdKey ] = children ;
398458 }
399-
400- parentsDictionary [ parentIdKey ] . Add ( scimRepresentationAttribute ) ;
459+ children . Add ( attr ) ;
401460 }
402461
403- foreach ( var node in treeNodes )
462+ foreach ( var node in attributesList )
404463 {
405- if ( parentsDictionary . ContainsKey ( node . Id ) )
464+ if ( parentsDictionary . TryGetValue ( node . Id , out var children ) )
406465 {
407- node . CachedChildren = parentsDictionary [ node . Id ] ;
408- node . Children = parentsDictionary [ node . Id ] ;
466+ node . CachedChildren = children ;
467+ node . Children = children ;
409468 }
410469 else
411470 {
412- var lst = new List < SCIMRepresentationAttribute > ( ) ;
413- node . CachedChildren = lst ;
414- node . Children = lst ;
471+ node . CachedChildren = emptyList ;
472+ node . Children = emptyList ;
415473 }
416474 }
417- var attrWithNoParentLst = attributes . Where ( a => a . ParentAttributeId == rootId || ! attributes . Any ( c => c . Id == a . ParentAttributeId ) ) . ToList ( ) ;
475+
476+ List < SCIMRepresentationAttribute > attrWithNoParentLst ;
477+ if ( parentsDictionary . TryGetValue ( rootId , out var rootChildren ) )
478+ {
479+ attrWithNoParentLst = new List < SCIMRepresentationAttribute > ( rootChildren . Count ) ;
480+ foreach ( var attr in rootChildren )
481+ {
482+ attrWithNoParentLst . Add ( attr ) ;
483+ }
484+
485+ foreach ( var attr in attributesList )
486+ {
487+ if ( ! string . IsNullOrEmpty ( attr . ParentAttributeId ) &&
488+ attr . ParentAttributeId != rootId &&
489+ ! existingIds . Contains ( attr . ParentAttributeId ) )
490+ {
491+ attrWithNoParentLst . Add ( attr ) ;
492+ }
493+ }
494+ }
495+ else
496+ {
497+ attrWithNoParentLst = new List < SCIMRepresentationAttribute > ( ) ;
498+ foreach ( var attr in attributesList )
499+ {
500+ if ( string . IsNullOrEmpty ( attr . ParentAttributeId ) ||
501+ ! existingIds . Contains ( attr . ParentAttributeId ) )
502+ {
503+ attrWithNoParentLst . Add ( attr ) ;
504+ }
505+ }
506+ }
507+
418508 foreach ( var attrWithNoParent in attrWithNoParentLst )
419509 {
420510 attrWithNoParent . ComputeValueIndex ( ) ;
0 commit comments