using System.Diagnostics.CodeAnalysis; using Speckle.Sdk.Models.Instances; namespace Speckle.Connectors.Common.Instances; public class InstanceObjectsManager : IInstanceObjectsManager { private readonly Dictionary _instanceProxies = new(); private readonly Dictionary> _instanceProxiesByDefinitionId = new(); private readonly Dictionary _definitionProxies = new(); private readonly Dictionary _flatAtomicObjects = new(); public void AddInstanceProxy(string objectId, InstanceProxy instanceProxy) => _instanceProxies[objectId] = instanceProxy; public void AddDefinitionProxy(string objectId, InstanceDefinitionProxy instanceDefinitionProxy) => _definitionProxies[objectId] = instanceDefinitionProxy; public void AddAtomicObject(string objectId, THostObjectType obj) => _flatAtomicObjects[objectId] = obj; public void AddInstanceProxiesByDefinitionId(string definitionId, List instanceProxies) => _instanceProxiesByDefinitionId[definitionId] = instanceProxies; public UnpackResult GetUnpackResult() => new(GetAtomicObjects(), GetInstanceProxies(), GetDefinitionProxies()); public bool TryGetInstanceProxiesFromDefinitionId( string definitionId, [NotNullWhen(true)] out List? instanceProxiesWithSameDefinition ) { if (_instanceProxiesByDefinitionId.TryGetValue(definitionId, out List? value)) { instanceProxiesWithSameDefinition = value; return true; } instanceProxiesWithSameDefinition = null; return false; } public bool TryGetInstanceDefinitionProxy( string definitionId, [NotNullWhen(true)] out InstanceDefinitionProxy? instanceDefinitionProxy ) { if (_definitionProxies.TryGetValue(definitionId, out InstanceDefinitionProxy? value)) { instanceDefinitionProxy = value; return true; } instanceDefinitionProxy = null; return false; } public InstanceProxy GetInstanceProxy(string instanceId) => _instanceProxies[instanceId]; private List GetAtomicObjects() => _flatAtomicObjects.Values.ToList(); private List GetDefinitionProxies() => _definitionProxies.Values.ToList(); private Dictionary GetInstanceProxies() => _instanceProxies; /// /// Update children max depths whenever definition proxy is found on the unpacked dictionary (). /// Even if definition unpacked before, max depth of its children must be updated if upcoming max depth is higher than existing one. /// /// Definition proxy to update max depth of its children. /// Value to increase max depth of children. public void UpdateChildrenMaxDepth(InstanceDefinitionProxy definitionProxy, int depthDifference) { // Increase depth of definition definitionProxy.maxDepth += depthDifference; // Find instance proxies of given definition var definitionInstanceProxies = definitionProxy .objects.Where(id => _instanceProxies.TryGetValue(id, out _)) .Select(id => _instanceProxies[id]) .ToList(); // Break the loop if no instance proxy found under definition. if (definitionInstanceProxies.Count == 0) { return; } var subDefinitions = new Dictionary(); foreach (InstanceProxy instanceProxy in definitionInstanceProxies) { // Increase depth of instance instanceProxy.maxDepth += depthDifference; // Collect sub definitions subDefinitions[instanceProxy.definitionId] = _definitionProxies[instanceProxy.definitionId]; } // Iterate through sub definitions foreach (var subDefinition in subDefinitions.Values) { UpdateChildrenMaxDepth(subDefinition, depthDifference); } } }