| | | 1 | | using Bpmn.Semantics; |
| | | 2 | | using Elsa.Bpmn.Interchange.Services; |
| | | 3 | | |
| | | 4 | | namespace Elsa.Bpmn.Interchange.Endpoints.Bpmn; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// Formats a <see cref="BpmnCapabilityException"/> into the one error message every endpoint that imports a BPMN |
| | | 8 | | /// document — <c>Import</c> and the document <c>Put</c> endpoint — reports it as. |
| | | 9 | | /// </summary> |
| | | 10 | | /// <remarks> |
| | | 11 | | /// <see cref="BpmnCapabilityException"/> carries <see cref="BpmnCapabilityException.DrivingElementIds"/> as a single |
| | | 12 | | /// flat list, already unioned across every missing capability — it does not say which element drove which capability |
| | | 13 | | /// (unlike <c>BpmnCapabilityRequirements.DrivingElementIds</c>, which is per-capability, but that type is gone by the |
| | | 14 | | /// time an endpoint's catch clause sees the exception). Attributing the full, unioned list to each capability |
| | | 15 | | /// individually would put elements next to a capability they may have nothing to do with, so this reports the |
| | | 16 | | /// missing capabilities together with the combined element list once, rather than repeating it. |
| | | 17 | | /// </remarks> |
| | | 18 | | internal static class BpmnCapabilityErrorFormatter |
| | | 19 | | { |
| | | 20 | | /// <summary>The message an endpoint reports for <paramref name="exception"/>.</summary> |
| | | 21 | | public static string Format(BpmnCapabilityException exception) |
| | | 22 | | { |
| | 1 | 23 | | var missingCapabilities = string.Join(", ", MissingCapabilityNames(exception)); |
| | 1 | 24 | | var elementIds = string.Join(", ", exception.DrivingElementIds); |
| | | 25 | | |
| | 1 | 26 | | return |
| | 1 | 27 | | $"This deployment does not declare the following BPMN host capabilities the document requires: {missingCapab |
| | 1 | 28 | | + $"Offending elements (combined across all missing capabilities above, not attributable to any one of them) |
| | | 29 | | } |
| | | 30 | | |
| | | 31 | | /// <summary> |
| | | 32 | | /// The structured <c>data</c> the <see cref="BpmnErrorCodes.ImportCapabilityUnsupported"/> response carries |
| | | 33 | | /// alongside <see cref="Format"/>'s message: the missing capability names and the offending element ids, under |
| | | 34 | | /// the same "combined, not attributable to any one capability" caveat <see cref="Format"/>'s remarks explain. |
| | | 35 | | /// </summary> |
| | 1 | 36 | | public static object DataFor(BpmnCapabilityException exception) => new |
| | 1 | 37 | | { |
| | 1 | 38 | | Capabilities = MissingCapabilityNames(exception), |
| | 1 | 39 | | ElementIds = exception.DrivingElementIds |
| | 1 | 40 | | }; |
| | | 41 | | |
| | | 42 | | private static IReadOnlyList<string> MissingCapabilityNames(BpmnCapabilityException exception) => |
| | 2 | 43 | | BpmnInterchangeDocumentService.IndividualCapabilities |
| | 8 | 44 | | .Where(capability => exception.Missing.HasFlag(capability)) |
| | 2 | 45 | | .Select(capability => capability.ToString()) |
| | 2 | 46 | | .ToList(); |
| | | 47 | | } |