< Summary

Information
Class: AsiBackbone.Core.Constraints.ConstraintEvaluationResult
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Constraints/ConstraintEvaluationResult.cs
Line coverage
100%
Covered lines: 73
Uncovered lines: 0
Coverable lines: 73
Total lines: 252
Line coverage: 100%
Branch coverage
100%
Covered branches: 28
Total branches: 28
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
get_Outcome()100%11100%
get_Reasons()100%11100%
get_ReasonCodes()100%11100%
get_CanProceed()100%11100%
get_IsDenied()100%11100%
get_IsWarning()100%11100%
get_IsNotApplicable()100%11100%
get_HasReasons()100%11100%
Allow()100%11100%
NotApplicable()100%11100%
Deny(...)100%11100%
Deny(...)100%11100%
Deny(...)100%11100%
Warning(...)100%11100%
Warning(...)100%11100%
Warning(...)100%11100%
NormalizeReasons(...)100%2424100%
CreateFallbackReason(...)100%11100%
CreateReasonCodes(...)100%44100%

File(s)

/home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Constraints/ConstraintEvaluationResult.cs

#LineLine coverage
 1using System.Collections.ObjectModel;
 2using AsiBackbone.Core.Results;
 3
 4namespace AsiBackbone.Core.Constraints;
 5
 6/// <summary>
 7/// Represents the framework-neutral result of evaluating a constraint.
 8/// </summary>
 9public sealed class ConstraintEvaluationResult
 10{
 11    private const string DefaultDeniedCode = "constraint.denied";
 12    private const string DefaultDeniedMessage = "Constraint denied the operation.";
 13    private const string DefaultWarningCode = "constraint.warning";
 14    private const string DefaultWarningMessage = "Constraint produced a warning.";
 15
 416    private static readonly OperationReason[] EmptyReasons = [];
 17
 418    private static readonly ReadOnlyCollection<string> EmptyReasonCodes =
 419        Array.AsReadOnly(Array.Empty<string>());
 20
 421    private static readonly ConstraintEvaluationResult AllowedResult =
 422        new(ConstraintEvaluationOutcome.Allowed, EmptyReasons);
 23
 424    private static readonly ConstraintEvaluationResult NotApplicableResult =
 425        new(ConstraintEvaluationOutcome.NotApplicable, EmptyReasons);
 26
 21527    private ConstraintEvaluationResult(
 21528        ConstraintEvaluationOutcome outcome,
 21529        IReadOnlyList<OperationReason> reasons)
 30    {
 21531        Outcome = outcome;
 21532        Reasons = reasons;
 21533        ReasonCodes = CreateReasonCodes(reasons);
 21534    }
 35
 36    /// <summary>
 37    /// Gets the constraint evaluation outcome.
 38    /// </summary>
 104439    public ConstraintEvaluationOutcome Outcome { get; }
 40
 41    /// <summary>
 42    /// Gets reasons associated with denied or warning outcomes.
 43    /// </summary>
 33944    public IReadOnlyList<OperationReason> Reasons { get; }
 45
 46    /// <summary>
 47    /// Gets machine-readable reason codes associated with denied or warning outcomes.
 48    /// </summary>
 4649    public IReadOnlyList<string> ReasonCodes { get; }
 50
 51    /// <summary>
 52    /// Gets a value indicating whether the constraint allows the operation to proceed.
 53    /// </summary>
 2054    public bool CanProceed => Outcome is not ConstraintEvaluationOutcome.Denied;
 55
 56    /// <summary>
 57    /// Gets a value indicating whether this result denies the operation.
 58    /// </summary>
 53259    public bool IsDenied => Outcome is ConstraintEvaluationOutcome.Denied;
 60
 61    /// <summary>
 62    /// Gets a value indicating whether this result contains warnings.
 63    /// </summary>
 44664    public bool IsWarning => Outcome is ConstraintEvaluationOutcome.Warning;
 65
 66    /// <summary>
 67    /// Gets a value indicating whether this result is not applicable to the supplied context.
 68    /// </summary>
 1269    public bool IsNotApplicable => Outcome is ConstraintEvaluationOutcome.NotApplicable;
 70
 71    /// <summary>
 72    /// Gets a value indicating whether the result contains reason data.
 73    /// </summary>
 874    public bool HasReasons => Reasons.Count > 0;
 75
 76    /// <summary>
 77    /// Creates an allowed constraint result.
 78    /// </summary>
 79    /// <returns>An allowed constraint evaluation result.</returns>
 80    public static ConstraintEvaluationResult Allow()
 81    {
 14282        return AllowedResult;
 83    }
 84
 85    /// <summary>
 86    /// Creates a not-applicable constraint result.
 87    /// </summary>
 88    /// <returns>A not-applicable constraint evaluation result.</returns>
 89    public static ConstraintEvaluationResult NotApplicable()
 90    {
 3491        return NotApplicableResult;
 92    }
 93
 94    /// <summary>
 95    /// Creates a denied constraint result.
 96    /// </summary>
 97    /// <param name="code">The machine-readable reason code.</param>
 98    /// <param name="message">The human-readable reason message.</param>
 99    /// <returns>A denied constraint evaluation result.</returns>
 100    public static ConstraintEvaluationResult Deny(string code, string message)
 101    {
 93102        return Deny(OperationReason.Create(code, message));
 103    }
 104
 105    /// <summary>
 106    /// Creates a denied constraint result.
 107    /// </summary>
 108    /// <param name="reason">The reason associated with the denied result.</param>
 109    /// <returns>A denied constraint evaluation result.</returns>
 110    public static ConstraintEvaluationResult Deny(OperationReason reason)
 111    {
 97112        ArgumentNullException.ThrowIfNull(reason);
 113
 95114        return new ConstraintEvaluationResult(
 95115            ConstraintEvaluationOutcome.Denied,
 95116            Array.AsReadOnly([reason]));
 117    }
 118
 119    /// <summary>
 120    /// Creates a denied constraint result.
 121    /// </summary>
 122    /// <param name="reasons">The reasons associated with the denied result.</param>
 123    /// <returns>A denied constraint evaluation result.</returns>
 124    public static ConstraintEvaluationResult Deny(IEnumerable<OperationReason> reasons)
 125    {
 16126        return new ConstraintEvaluationResult(
 16127            ConstraintEvaluationOutcome.Denied,
 16128            NormalizeReasons(reasons, DefaultDeniedCode, DefaultDeniedMessage));
 129    }
 130
 131    /// <summary>
 132    /// Creates a warning constraint result.
 133    /// </summary>
 134    /// <param name="code">The machine-readable reason code.</param>
 135    /// <param name="message">The human-readable reason message.</param>
 136    /// <returns>A warning constraint evaluation result.</returns>
 137    public static ConstraintEvaluationResult Warning(string code, string message)
 138    {
 74139        return Warning(OperationReason.Create(code, message));
 140    }
 141
 142    /// <summary>
 143    /// Creates a warning constraint result.
 144    /// </summary>
 145    /// <param name="reason">The reason associated with the warning result.</param>
 146    /// <returns>A warning constraint evaluation result.</returns>
 147    public static ConstraintEvaluationResult Warning(OperationReason reason)
 148    {
 78149        ArgumentNullException.ThrowIfNull(reason);
 150
 76151        return new ConstraintEvaluationResult(
 76152            ConstraintEvaluationOutcome.Warning,
 76153            Array.AsReadOnly([reason]));
 154    }
 155
 156    /// <summary>
 157    /// Creates a warning constraint result.
 158    /// </summary>
 159    /// <param name="reasons">The reasons associated with the warning result.</param>
 160    /// <returns>A warning constraint evaluation result.</returns>
 161    public static ConstraintEvaluationResult Warning(IEnumerable<OperationReason> reasons)
 162    {
 10163        return new ConstraintEvaluationResult(
 10164            ConstraintEvaluationOutcome.Warning,
 10165            NormalizeReasons(reasons, DefaultWarningCode, DefaultWarningMessage));
 166    }
 167
 168    private static ReadOnlyCollection<OperationReason> NormalizeReasons(
 169        IEnumerable<OperationReason>? reasons,
 170        string fallbackCode,
 171        string fallbackMessage)
 172    {
 26173        if (reasons is null)
 174        {
 4175            return CreateFallbackReason(fallbackCode, fallbackMessage);
 176        }
 177
 22178        if (reasons is ICollection<OperationReason> collection)
 179        {
 18180            if (collection.Count == 0)
 181            {
 4182                return CreateFallbackReason(fallbackCode, fallbackMessage);
 183            }
 184
 14185            var normalizedReasons = new OperationReason[collection.Count];
 14186            int normalizedCount = 0;
 187
 84188            foreach (OperationReason? reason in collection)
 189            {
 28190                if (reason is not null)
 191                {
 16192                    normalizedReasons[normalizedCount] = reason;
 16193                    normalizedCount++;
 194                }
 195            }
 196
 14197            if (normalizedCount == 0)
 198            {
 4199                return CreateFallbackReason(fallbackCode, fallbackMessage);
 200            }
 201
 10202            if (normalizedCount == normalizedReasons.Length)
 203            {
 2204                return Array.AsReadOnly(normalizedReasons);
 205            }
 206
 8207            var filteredReasons = new OperationReason[normalizedCount];
 8208            Array.Copy(normalizedReasons, filteredReasons, normalizedCount);
 209
 8210            return Array.AsReadOnly(filteredReasons);
 211        }
 212
 4213        List<OperationReason>? normalizedList = null;
 214
 16215        foreach (OperationReason? reason in reasons)
 216        {
 4217            if (reason is not null)
 218            {
 4219                normalizedList ??= [];
 4220                normalizedList.Add(reason);
 221            }
 222        }
 223
 4224        return normalizedList is null || normalizedList.Count == 0
 4225            ? CreateFallbackReason(fallbackCode, fallbackMessage)
 4226            : Array.AsReadOnly([.. normalizedList]);
 227    }
 228
 229    private static ReadOnlyCollection<OperationReason> CreateFallbackReason(
 230        string fallbackCode,
 231        string fallbackMessage)
 232    {
 14233        return Array.AsReadOnly([OperationReason.Create(fallbackCode, fallbackMessage)]);
 234    }
 235
 236    private static ReadOnlyCollection<string> CreateReasonCodes(IReadOnlyList<OperationReason> reasons)
 237    {
 215238        if (reasons.Count == 0)
 239        {
 12240            return EmptyReasonCodes;
 241        }
 242
 203243        string[] reasonCodes = new string[reasons.Count];
 244
 828245        for (int index = 0; index < reasons.Count; index++)
 246        {
 211247            reasonCodes[index] = reasons[index].Code;
 248        }
 249
 203250        return Array.AsReadOnly(reasonCodes);
 251    }
 252}