< Summary

Information
Class: Elsa.Workflows.IdentityGraphService
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Services/IdentityGraphService.cs
Line coverage
100%
Covered lines: 51
Uncovered lines: 0
Coverable lines: 51
Total lines: 123
Line coverage: 100%
Branch coverage
100%
Covered branches: 30
Total branches: 30
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
AssignIdentitiesAsync()100%11100%
AssignIdentitiesAsync()100%11100%
AssignIdentitiesAsync(...)100%11100%
AssignIdentitiesAsync()100%44100%
AssignInputOutputsAsync()100%1616100%
AssignVariables(...)100%44100%
CreateId(...)100%44100%
GetNextIndexFor(...)100%22100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Services/IdentityGraphService.cs

#LineLine coverage
 1using Elsa.Extensions;
 2using Elsa.Workflows.Activities;
 3using Elsa.Workflows.Models;
 4using Humanizer;
 5using Microsoft.Extensions.Logging;
 6
 7namespace Elsa.Workflows;
 8
 9/// <inheritdoc />
 102110public class IdentityGraphService(IActivityVisitor activityVisitor, IActivityRegistryLookupService activityRegistryLooku
 11{
 12    /// <inheritdoc />
 13    public async Task AssignIdentitiesAsync(Workflow workflow, CancellationToken cancellationToken = default)
 14    {
 275615        await AssignIdentitiesAsync((IActivity)workflow, cancellationToken);
 275616    }
 17
 18    /// <inheritdoc />
 19    public async Task AssignIdentitiesAsync(IActivity root, CancellationToken cancellationToken = default)
 20    {
 275621        var graph = await activityVisitor.VisitAsync(root, cancellationToken);
 275622        await AssignIdentitiesAsync(graph);
 275623    }
 24
 25    /// <inheritdoc />
 275626    public Task AssignIdentitiesAsync(ActivityNode root) => AssignIdentitiesAsync(root.Flatten().ToList());
 27
 28    /// <inheritdoc />
 29    public async Task AssignIdentitiesAsync(ICollection<ActivityNode> flattenedList)
 30    {
 970531        var identityCounters = new Dictionary<string, int>();
 32
 10202833        foreach (var node in flattenedList)
 34        {
 4130935            node.Activity.Id = CreateId(node, identityCounters, flattenedList);
 4130936            node.Activity.NodeId = node.NodeId;
 4130937            await AssignInputOutputsAsync(node.Activity);
 38
 4130939            if (node.Activity is IVariableContainer variableContainer)
 2100640                AssignVariables(variableContainer);
 4130941        }
 970542    }
 43
 44    /// <inheritdoc />
 45    public async Task AssignInputOutputsAsync(IActivity activity)
 46    {
 4130947        var activityDescriptor = await activityRegistryLookup.FindAsync(activity.Type, activity.Version);
 48
 4130949        if (activityDescriptor == null!)
 50        {
 64451            logger.LogWarning("Activity descriptor not found for activity type {ActivityType}. Skipping identity assignm
 64452            return;
 53        }
 54
 4066555        var inputDictionary = activityDescriptor.GetWrappedInputProperties(activity);
 56
 18183457        foreach (var (inputName, input) in inputDictionary)
 58        {
 5025259            var blockReference = input?.MemoryBlockReference();
 60
 5025261            if (blockReference == null!)
 62                continue;
 63
 3287964            if (string.IsNullOrEmpty(blockReference.Id))
 1772465                blockReference.Id = $"{activity.Id}:input-{inputName.Humanize().Kebaberize()}";
 66        }
 67
 4066568        var outputs = activity.GetOutputs();
 69
 9947470        foreach (var output in outputs)
 71        {
 907272            var blockReference = output.Value.MemoryBlockReference();
 73
 907274            if (blockReference == null!)
 75                continue;
 76
 907277            if (string.IsNullOrEmpty(blockReference.Id))
 384278                blockReference.Id = $"{activity.Id}:output-{output.Name.Humanize().Kebaberize()}";
 79        }
 4130980    }
 81
 82    /// <inheritdoc />
 83    public void AssignVariables(IVariableContainer activity)
 84    {
 2100685        var variables = activity.Variables;
 2100686        var seed = 0;
 87
 4723888        foreach (var variable in variables)
 261389            variable.Id = variable.Id != null! ? variable.Id : $"{activity.Id}:variable-{++seed}";
 2100690    }
 91
 92    private string CreateId(ActivityNode activityNode, IDictionary<string, int> identityCounters, ICollection<ActivityNo
 93    {
 4130994        if (!string.IsNullOrWhiteSpace(activityNode.Activity.Id))
 2286695            return activityNode.Activity.Id;
 96
 97        while (true)
 98        {
 1937899            var fullTypeName = activityNode.Activity.Type;
 19378100            var shortTypeName = fullTypeName.Split('.').Last();
 19378101            var index = GetNextIndexFor(shortTypeName, identityCounters);
 19378102            var name = $"{shortTypeName}{index + 1}";
 103
 112513104            if (allNodes.All(x => x.Activity.Id != name))
 18443105                return name;
 106        }
 107    }
 108
 109    private int GetNextIndexFor(string activityType, IDictionary<string, int> identityCounters)
 110    {
 19378111        if (!identityCounters.TryGetValue(activityType, out var index))
 112        {
 17075113            identityCounters[activityType] = index;
 114        }
 115        else
 116        {
 2303117            index = identityCounters[activityType] + 1;
 2303118            identityCounters[activityType] = index;
 119        }
 120
 19378121        return index;
 122    }
 123}