using Speckle.Automate.Sdk;
using Speckle.Automate.Sdk.Schema;
using Speckle.Core.Api;
using Speckle.Core.Models;
using Speckle.Core.Models.Extensions;
using Speckle.Core.Transports;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SpeckleAutomateDotnetExample
{
internal class Utils
{
///
/// Receives a commit object from the same project and account as the
///
/// The id of the commit to receive
/// The Automation context
///
///
public static async Task RecieveVersionAsync(
string commitId,
AutomationContext context
)
{
ServerTransport serverTransport = new ServerTransport(
context.SpeckleClient.Account,
context.AutomationRunData.ProjectId
);
Base? receivedCommitObject = await Operations
.Receive(
(
await context.SpeckleClient
.CommitGet(context.AutomationRunData.ProjectId, commitId)
.ConfigureAwait(continueOnCapturedContext: false)
).referencedObject,
serverTransport,
new MemoryTransport()
)
.ConfigureAwait(continueOnCapturedContext: false);
if (receivedCommitObject == null)
{
throw new Exception("Commit root object was null");
}
return receivedCommitObject;
}
///
/// Creates Dictionaries from a commit Base, using applicationId if available or speckle id if no applicationId exists.
///
/// The commit Base to create dictionaries from
/// The dictionary of commit objects sorted by applicationId
/// The dictionary of commit objects without applicationIds, sorted by speckle id
public static void CreateDictionaryFromBaseById(
Base commit,
out Dictionary> appIdDict,
out Dictionary> speckleIdDict,
out int objectCount
)
{
IEnumerable commitObjects = commit.Flatten();
objectCount = commitObjects.Count();
appIdDict = new Dictionary>();
speckleIdDict = new Dictionary>();
foreach (var commitObject in commitObjects)
{
if (!string.IsNullOrWhiteSpace(commitObject.applicationId))
{
if (appIdDict.ContainsKey(commitObject.applicationId))
{
appIdDict[commitObject.applicationId].Add(commitObject);
}
else
{
appIdDict.Add(
commitObject.applicationId,
new List() { commitObject }
);
}
}
else if (!string.IsNullOrWhiteSpace(commitObject.id))
{
if (speckleIdDict.ContainsKey(commitObject.id))
{
speckleIdDict[commitObject.id].Add(commitObject);
}
else
{
speckleIdDict.Add(commitObject.id, new List() { commitObject });
}
}
}
}
///
/// Filters two lists by removing all objects from with a matching speckle id in
///
/// The list to filter
/// The list to filter against
/// A list of matches found in
public static List> FilterListsBySpeckleIdMatch(
List setA,
List setB
)
{
var matches = new List>();
for (int i = setA.Count - 1; i >= 0; i--)
{
var testObject = setA[i];
for (int j = setB.Count - 1; j >= 0; j--)
{
var releaseObject = setB[j];
// if a match was found, remove from both lists and add to matches
if (testObject.id == releaseObject.id)
{
matches.Add(
new Tuple(
testObject.id,
testObject.applicationId,
testObject.speckle_type
)
);
setA.RemoveAt(i);
setB.RemoveAt(j);
}
}
}
return matches;
}
///
/// Compares the properties of against
///
///
///
/// Properties on that do not exist on
/// Properties on that do not exist on
/// Properties on that have a different value on . The second string is the category of modification (eg count/primitive/base)
public static void CompareBaseProperties(
Base a,
Base b,
out List addedProps,
out List deletedProps,
out List> modifiedProps
)
{
addedProps = new List();
deletedProps = new List();
modifiedProps = new List>();
Dictionary bObjectPropDict = b.GetMembers();
Dictionary aObjectPropDict = a.GetMembers();
foreach (KeyValuePair entry in aObjectPropDict)
{
if (bObjectPropDict.ContainsKey(entry.Key))
{
bool changed = !IsEqual(
entry.Value,
bObjectPropDict[entry.Key],
out string category
);
if (changed)
{
modifiedProps.Add(new Tuple(entry.Key, category));
}
bObjectPropDict.Remove(entry.Key);
}
else
{
addedProps.Add(entry.Key);
}
}
// check if there are any props left on the b - these were missing in the a
foreach (var entry in bObjectPropDict)
{
deletedProps.Add(entry.Key);
}
}
///
/// Determines equality between two objects
///
///
///
///
/// The category of the modification, if objects are not equal
///
public static bool IsEqual(T a, T b, out string category)
{
category = "Value";
switch (a)
{
case Base aBase:
if (b is Base bBase && bBase.speckle_type == aBase.speckle_type)
{
return aBase.id == bBase.id;
}
else
{
category = "Type";
return false;
}
case List