public void Execute(DB.UpdaterData data) { if (AddedElementIds is null) { AddedElementIds = data.GetAddedElementIds(); } else { foreach (var item in data.GetAddedElementIds()) { AddedElementIds.Add(item); } } if (DeletedElementIds is null) { DeletedElementIds = data.GetDeletedElementIds(); } else { foreach (var item in data.GetDeletedElementIds()) { DeletedElementIds.Add(item); } } if (ModifiedElementIds is null) { ModifiedElementIds = data.GetModifiedElementIds(); } else { foreach (var item in data.GetModifiedElementIds()) { ModifiedElementIds.Add(item); } } Debug.Assert(AddedElementIds.Count == 0); if (ModifiedElementIds.Count > 0) { var message = new DB.FailureMessage(DBX.ExternalFailures.ElementFailures.FailedToPurgeElement); message.SetFailingElements(ElementIds); message.SetAdditionalElements(data.GetModifiedElementIds()); data.GetDocument().PostFailure(message); } }
protected override void TrySolveInstance(IGH_DataAccess DA) { var elementList = new List <Types.IGH_Element>(); if (!DA.GetDataList("Elements", elementList)) { return; } try { var elementGroups = elementList. GroupBy(x => x.Document). ToArray(); if (elementGroups.Length > 0) { var transactionGroups = new Queue <DB.TransactionGroup>(); try { var Succeeded = true; var Deleted = new List <Types.Element>(); var Modified = new List <Types.Element>(); foreach (var elementGroup in elementGroups) { var doc = elementGroup.Key; // Start a transaction Group to be able to rollback in case changes in different documents fails. { var group = new DB.TransactionGroup(doc, Name); if (group.Start() != DB.TransactionStatus.Started) { group.Dispose(); continue; } transactionGroups.Enqueue(group); } ClassifyElementIds(elementGroup, out var elements, out var types); // Step 1. Purge non ElementTypes Succeeded &= Purge(doc, elements, Deleted, Modified); // Step 2. Check if ElementTypes to be purged are still in use in the model by any Instance if (types.Count > 0) { var typesInUse = new List <DB.ElementId>(types.Count); // Remove purgable ElementTypes from types if (doc.GetPurgableElementTypes(out var purgableTypes)) { foreach (var type in types) { if (!purgableTypes.Contains(type)) { typesInUse.Add(type); } } } // Post a FailureMessage in case we have non purgable ElementTypes on types if (typesInUse.Count > 0) { using (var transaction = NewTransaction(doc)) { transaction.Start(); using (var message = new DB.FailureMessage(DBX.ExternalFailures.ElementFailures.FailedToPurgeElement)) { message.SetFailingElements(typesInUse); doc.PostFailure(message); } CommitTransaction(doc, transaction); } Succeeded &= false; } } // Step 3. Purge ElementTypes // Types include typesInUse in order to get information about Deleted and Modified elements. Succeeded &= Purge(doc, types, Deleted, Modified); } if (Succeeded && !Simulated) { deletedElements += Deleted.Count; // Transactions in all documents succeded, it's fine to assimilate all changes as one. while (transactionGroups.Count > 0) { using (var group = transactionGroups.Dequeue()) { group.Assimilate(); } } } DA.SetData("Succeeded", Succeeded); DA.SetDataList("Deleted", Deleted); DA.SetDataList("Modified", Modified); } catch (Autodesk.Revit.Exceptions.ArgumentException) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "One or many of the elements cannot be deleted or are invalid."); DA.SetData("Succeeded", false); } finally { // In case we still have transaction groups here something bad happened foreach (var group in transactionGroups.Cast <DB.TransactionGroup>().Reverse()) { using (group) { group.RollBack(); } } } } } catch (NullReferenceException) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "One or many of the elements are Null."); } }