Files
speckle-sharp-connectors/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadGroupBaker.cs
T
Adam Hathcock 332ab25e64 Use Sets and Freezing to make conversions faster (#430)
* Use Sets and Freezing to make conversions faster

* fmt

* move class to own file
2024-12-03 13:32:27 +00:00

82 lines
2.9 KiB
C#

using Autodesk.AutoCAD.DatabaseServices;
using Microsoft.Extensions.Logging;
using Speckle.Connectors.Common.Conversion;
using Speckle.Sdk;
using Speckle.Sdk.Dependencies;
using Speckle.Sdk.Models.Proxies;
namespace Speckle.Connectors.Autocad.HostApp;
/// <summary>
/// This resource expects to be injected "fresh" in each receive operation (scoped lifetime).
/// Extracts group information from a set of objects into proxies in send operations; also creates groups from a set of proxies in receive operations.
/// TODO: Oguzhan! Check whats happening on second receive unless purge groups? naming etc..
/// </summary>
public class AutocadGroupBaker
{
private readonly ILogger<AutocadGroupBaker> _logger;
private readonly AutocadContext _autocadContext;
public AutocadGroupBaker(AutocadContext autocadContext, ILogger<AutocadGroupBaker> logger)
{
_autocadContext = autocadContext;
_logger = logger;
}
/// <summary>
/// Creates groups in the host app from a set of group proxies. Can be called after the bake operation of all atomic objects (including instances) is complete.
/// </summary>
/// <param name="groupProxies"></param>
/// <param name="applicationIdMap"></param>
/// <returns></returns>
// TODO: Oguzhan! Do not report here too! But this is TBD that we don't know the shape of the report yet.
public IReadOnlyCollection<ReceiveConversionResult> CreateGroups(
IEnumerable<GroupProxy> groupProxies,
Dictionary<string, IReadOnlyCollection<Entity>> applicationIdMap
)
{
HashSet<ReceiveConversionResult> results = new();
using var groupCreationTransaction =
Application.DocumentManager.CurrentDocument.Database.TransactionManager.StartTransaction();
var groupDictionary = (DBDictionary)
groupCreationTransaction.GetObject(
Application.DocumentManager.CurrentDocument.Database.GroupDictionaryId,
OpenMode.ForWrite
);
foreach (var gp in groupProxies.OrderBy(group => group.objects.Count))
{
try
{
var entities = gp.objects.SelectMany(oldObjId => applicationIdMap[oldObjId]);
var ids = new ObjectIdCollection();
foreach (var entity in entities)
{
ids.Add(entity.ObjectId);
}
var groupName = _autocadContext.RemoveInvalidChars(gp.name);
var newGroup = new Group(groupName, true); // NOTE: this constructor sets both the description (as it says) but also the name at the same time
newGroup.Append(ids);
groupDictionary.UpgradeOpen();
groupDictionary.SetAt(groupName, newGroup);
groupCreationTransaction.AddNewlyCreatedDBObject(newGroup, true);
}
catch (Exception ex) when (!ex.IsFatal())
{
results.Add(new ReceiveConversionResult(Status.ERROR, gp, null, null, ex));
_logger.LogError(ex, "Failed to bake Autocad Group");
}
}
groupCreationTransaction.Commit();
return results.Freeze();
}
}