< 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: 70
Uncovered lines: 0
Coverable lines: 70
Total lines: 247
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
 116    private static readonly IReadOnlyList<OperationReason> EmptyReasons =
 117        Array.AsReadOnly(Array.Empty<OperationReason>());
 18
 119    private static readonly ReadOnlyCollection<string> EmptyReasonCodes =
 120        Array.AsReadOnly(Array.Empty<string>());
 21
 8422    private ConstraintEvaluationResult(
 8423        ConstraintEvaluationOutcome outcome,
 8424        IReadOnlyList<OperationReason> reasons)
 25    {
 8426        Outcome = outcome;
 8427        Reasons = reasons;
 8428        ReasonCodes = CreateReasonCodes(reasons);
 8429    }
 30
 31    /// <summary>
 32    /// Gets the constraint evaluation outcome.
 33    /// </summary>
 15234    public ConstraintEvaluationOutcome Outcome { get; }
 35
 36    /// <summary>
 37    /// Gets reasons associated with denied or warning outcomes.
 38    /// </summary>
 5139    public IReadOnlyList<OperationReason> Reasons { get; }
 40
 41    /// <summary>
 42    /// Gets machine-readable reason codes associated with denied or warning outcomes.
 43    /// </summary>
 1544    public IReadOnlyList<string> ReasonCodes { get; }
 45
 46    /// <summary>
 47    /// Gets a value indicating whether the constraint allows the operation to proceed.
 48    /// </summary>
 1049    public bool CanProceed => Outcome is not ConstraintEvaluationOutcome.Denied;
 50
 51    /// <summary>
 52    /// Gets a value indicating whether this result denies the operation.
 53    /// </summary>
 7054    public bool IsDenied => Outcome is ConstraintEvaluationOutcome.Denied;
 55
 56    /// <summary>
 57    /// Gets a value indicating whether this result contains warnings.
 58    /// </summary>
 5359    public bool IsWarning => Outcome is ConstraintEvaluationOutcome.Warning;
 60
 61    /// <summary>
 62    /// Gets a value indicating whether this result is not applicable to the supplied context.
 63    /// </summary>
 664    public bool IsNotApplicable => Outcome is ConstraintEvaluationOutcome.NotApplicable;
 65
 66    /// <summary>
 67    /// Gets a value indicating whether the result contains reason data.
 68    /// </summary>
 469    public bool HasReasons => Reasons.Count > 0;
 70
 71    /// <summary>
 72    /// Creates an allowed constraint result.
 73    /// </summary>
 74    /// <returns>An allowed constraint evaluation result.</returns>
 75    public static ConstraintEvaluationResult Allow()
 76    {
 2377        return new ConstraintEvaluationResult(ConstraintEvaluationOutcome.Allowed, EmptyReasons);
 78    }
 79
 80    /// <summary>
 81    /// Creates a not-applicable constraint result.
 82    /// </summary>
 83    /// <returns>A not-applicable constraint evaluation result.</returns>
 84    public static ConstraintEvaluationResult NotApplicable()
 85    {
 1086        return new ConstraintEvaluationResult(ConstraintEvaluationOutcome.NotApplicable, EmptyReasons);
 87    }
 88
 89    /// <summary>
 90    /// Creates a denied constraint result.
 91    /// </summary>
 92    /// <param name="code">The machine-readable reason code.</param>
 93    /// <param name="message">The human-readable reason message.</param>
 94    /// <returns>A denied constraint evaluation result.</returns>
 95    public static ConstraintEvaluationResult Deny(string code, string message)
 96    {
 1797        return Deny(OperationReason.Create(code, message));
 98    }
 99
 100    /// <summary>
 101    /// Creates a denied constraint result.
 102    /// </summary>
 103    /// <param name="reason">The reason associated with the denied result.</param>
 104    /// <returns>A denied constraint evaluation result.</returns>
 105    public static ConstraintEvaluationResult Deny(OperationReason reason)
 106    {
 19107        ArgumentNullException.ThrowIfNull(reason);
 108
 18109        return new ConstraintEvaluationResult(
 18110            ConstraintEvaluationOutcome.Denied,
 18111            Array.AsReadOnly([reason]));
 112    }
 113
 114    /// <summary>
 115    /// Creates a denied constraint result.
 116    /// </summary>
 117    /// <param name="reasons">The reasons associated with the denied result.</param>
 118    /// <returns>A denied constraint evaluation result.</returns>
 119    public static ConstraintEvaluationResult Deny(IEnumerable<OperationReason> reasons)
 120    {
 8121        return new ConstraintEvaluationResult(
 8122            ConstraintEvaluationOutcome.Denied,
 8123            NormalizeReasons(reasons, DefaultDeniedCode, DefaultDeniedMessage));
 124    }
 125
 126    /// <summary>
 127    /// Creates a warning constraint result.
 128    /// </summary>
 129    /// <param name="code">The machine-readable reason code.</param>
 130    /// <param name="message">The human-readable reason message.</param>
 131    /// <returns>A warning constraint evaluation result.</returns>
 132    public static ConstraintEvaluationResult Warning(string code, string message)
 133    {
 19134        return Warning(OperationReason.Create(code, message));
 135    }
 136
 137    /// <summary>
 138    /// Creates a warning constraint result.
 139    /// </summary>
 140    /// <param name="reason">The reason associated with the warning result.</param>
 141    /// <returns>A warning constraint evaluation result.</returns>
 142    public static ConstraintEvaluationResult Warning(OperationReason reason)
 143    {
 21144        ArgumentNullException.ThrowIfNull(reason);
 145
 20146        return new ConstraintEvaluationResult(
 20147            ConstraintEvaluationOutcome.Warning,
 20148            Array.AsReadOnly([reason]));
 149    }
 150
 151    /// <summary>
 152    /// Creates a warning constraint result.
 153    /// </summary>
 154    /// <param name="reasons">The reasons associated with the warning result.</param>
 155    /// <returns>A warning constraint evaluation result.</returns>
 156    public static ConstraintEvaluationResult Warning(IEnumerable<OperationReason> reasons)
 157    {
 5158        return new ConstraintEvaluationResult(
 5159            ConstraintEvaluationOutcome.Warning,
 5160            NormalizeReasons(reasons, DefaultWarningCode, DefaultWarningMessage));
 161    }
 162
 163    private static ReadOnlyCollection<OperationReason> NormalizeReasons(
 164        IEnumerable<OperationReason>? reasons,
 165        string fallbackCode,
 166        string fallbackMessage)
 167    {
 13168        if (reasons is null)
 169        {
 2170            return CreateFallbackReason(fallbackCode, fallbackMessage);
 171        }
 172
 11173        if (reasons is ICollection<OperationReason> collection)
 174        {
 9175            if (collection.Count == 0)
 176            {
 2177                return CreateFallbackReason(fallbackCode, fallbackMessage);
 178            }
 179
 7180            var normalizedReasons = new OperationReason[collection.Count];
 7181            int normalizedCount = 0;
 182
 42183            foreach (OperationReason? reason in collection)
 184            {
 14185                if (reason is not null)
 186                {
 8187                    normalizedReasons[normalizedCount] = reason;
 8188                    normalizedCount++;
 189                }
 190            }
 191
 7192            if (normalizedCount == 0)
 193            {
 2194                return CreateFallbackReason(fallbackCode, fallbackMessage);
 195            }
 196
 5197            if (normalizedCount == normalizedReasons.Length)
 198            {
 1199                return Array.AsReadOnly(normalizedReasons);
 200            }
 201
 4202            var filteredReasons = new OperationReason[normalizedCount];
 4203            Array.Copy(normalizedReasons, filteredReasons, normalizedCount);
 204
 4205            return Array.AsReadOnly(filteredReasons);
 206        }
 207
 2208        List<OperationReason>? normalizedList = null;
 209
 8210        foreach (OperationReason? reason in reasons)
 211        {
 2212            if (reason is not null)
 213            {
 2214                normalizedList ??= [];
 2215                normalizedList.Add(reason);
 216            }
 217        }
 218
 2219        return normalizedList is null || normalizedList.Count == 0
 2220            ? CreateFallbackReason(fallbackCode, fallbackMessage)
 2221            : Array.AsReadOnly([.. normalizedList]);
 222    }
 223
 224    private static ReadOnlyCollection<OperationReason> CreateFallbackReason(
 225        string fallbackCode,
 226        string fallbackMessage)
 227    {
 7228        return Array.AsReadOnly([OperationReason.Create(fallbackCode, fallbackMessage)]);
 229    }
 230
 231    private static ReadOnlyCollection<string> CreateReasonCodes(IReadOnlyList<OperationReason> reasons)
 232    {
 84233        if (reasons.Count == 0)
 234        {
 33235            return EmptyReasonCodes;
 236        }
 237
 51238        string[] reasonCodes = new string[reasons.Count];
 239
 212240        for (int index = 0; index < reasons.Count; index++)
 241        {
 55242            reasonCodes[index] = reasons[index].Code;
 243        }
 244
 51245        return Array.AsReadOnly(reasonCodes);
 246    }
 247}