< Summary

Information
Class: Elsa.Bpmn.Interchange.Endpoints.Bpmn.Export.Export
Assembly: Elsa.Bpmn.Interchange
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Bpmn.Interchange/Endpoints/Bpmn/Export/Endpoint.cs
Line coverage
86%
Covered lines: 26
Uncovered lines: 4
Coverable lines: 30
Total lines: 82
Line coverage: 86.6%
Branch coverage
100%
Covered branches: 4
Total branches: 4
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%
Configure()100%11100%
HandleAsync()100%4484.61%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Bpmn.Interchange/Endpoints/Bpmn/Export/Endpoint.cs

#LineLine coverage
 1using Bpmn.Interchange;
 2using Elsa.Abstractions;
 3using Elsa.Bpmn.Interchange.Exceptions;
 4using Elsa.Bpmn.Interchange.Services;
 5using Elsa.Common.Models;
 6using Elsa.Workflows.Management;
 7using Elsa.Workflows.Models;
 8using JetBrains.Annotations;
 9using Microsoft.AspNetCore.Http;
 10
 11namespace Elsa.Bpmn.Interchange.Endpoints.Bpmn.Export;
 12
 13/// <summary>Writes a stored workflow definition back out as BPMN 2.0 XML.</summary>
 14/// <remarks>
 15/// A thin wrapper over <see cref="BpmnInterchangeDocumentService.Export(Elsa.Workflows.Management.Entities.WorkflowDefi
 16/// See that type's remarks for why this re-reads the original document rather than reconstructing one from the Elsa
 17/// activity graph the definition runs, and for why a missing or stale source is refused rather than exported anyway.
 18/// </remarks>
 19[UsedImplicitly]
 1520internal sealed class Export(IWorkflowDefinitionStore store, BpmnInterchangeDocumentService documentService) : ElsaEndpo
 21{
 22    /// <inheritdoc />
 23    public override void Configure()
 24    {
 1125        Get("bpmn/definitions/{definitionId}/export");
 1126        ConfigurePermissions("read:workflow-definitions");
 1127    }
 28
 29    /// <inheritdoc />
 30    public override async Task HandleAsync(Request request, CancellationToken cancellationToken)
 31    {
 32        VersionOptions versionOptions;
 33
 434        if (string.IsNullOrWhiteSpace(request.VersionOptions))
 35        {
 336            versionOptions = VersionOptions.Latest;
 37        }
 38        else
 39        {
 40            try
 41            {
 42                // VersionOptions.TryParse always returns true and still throws through FromString for a value it
 43                // cannot make sense of, so it buys nothing over calling FromString directly — catch what it can
 44                // actually throw instead: a non-numeric or out-of-range value that is not one of its named options.
 145                versionOptions = VersionOptions.FromString(request.VersionOptions);
 046            }
 147            catch (Exception exception) when (exception is FormatException or OverflowException)
 48            {
 149                AddError(
 150                    $"'{request.VersionOptions}' is not a valid version. Specify a whole number, or one of: AllVersions,
 151                    + "LatestOrPublished, LatestAndPublished.");
 152                await Send.ErrorsAsync(StatusCodes.Status400BadRequest, cancellationToken);
 153                return;
 54            }
 55        }
 56
 357        var filter = WorkflowDefinitionHandle.ByDefinitionId(request.DefinitionId, versionOptions).ToFilter();
 358        var definition = await store.FindAsync(filter, cancellationToken);
 59
 360        if (definition == null)
 61        {
 162            await Send.NotFoundAsync(cancellationToken);
 163            return;
 64        }
 65
 66        try
 67        {
 268            var bytes = documentService.Export(definition);
 169            await Send.BytesAsync(bytes, $"{request.DefinitionId}.bpmn", "application/xml", cancellation: cancellationTo
 170        }
 171        catch (BpmnExportUnavailableException exception)
 72        {
 173            AddError(exception.Message);
 174            await Send.ErrorsAsync(StatusCodes.Status422UnprocessableEntity, cancellationToken);
 175        }
 076        catch (BpmnInterchangeException exception)
 77        {
 078            AddError(exception.Message);
 079            await Send.ErrorsAsync(StatusCodes.Status400BadRequest, cancellationToken);
 80        }
 481    }
 82}