< Summary

Information
Class: Spdx3.Model.BaseModelClass
Assembly: Spdx3
File(s): /home/runner/work/Spdx3/Spdx3/Spdx3/Model/BaseModelClass.cs
Line coverage
100%
Covered lines: 28
Uncovered lines: 0
Coverable lines: 28
Total lines: 82
Line coverage: 100%
Branch coverage
100%
Covered branches: 14
Total branches: 14
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Type()100%11100%
get_SpdxId()100%11100%
get_Catalog()100%11100%
.ctor()100%11100%
.ctor(...)100%11100%
Validate()100%11100%
ValidateRequiredProperty(...)100%1414100%

File(s)

/home/runner/work/Spdx3/Spdx3/Spdx3/Model/BaseModelClass.cs

#LineLine coverage
 1using System.Collections;
 2using System.Diagnostics.CodeAnalysis;
 3using System.Reflection;
 4using System.Runtime.CompilerServices;
 5using System.Text.Json.Serialization;
 6using Spdx3.Exceptions;
 7using Spdx3.Serialization;
 8using Spdx3.Utility;
 9
 10namespace Spdx3.Model;
 11
 12/// <summary>
 13///     This is a base class for like EVERYTHING in an SPDX document, whether it's an "Element" or some other "Non-Eleme
 14///     class.
 15///     See https://spdx.github.io/spdx-spec/v3.0.1/annexes/rdf-model/
 16/// </summary>
 17public abstract class BaseModelClass
 18{
 19    [JsonPropertyName("type")]
 20    [JsonConverter(typeof(SpdxModelConverterFactory))]
 285621    public required string Type { get; set; }
 22
 23    [JsonPropertyName("spdxId")]
 24    [JsonConverter(typeof(SpdxModelConverterFactory))]
 439825    public required Uri SpdxId { get; set; }
 26
 27    // A back-link to the catalog that was used to created this item and now contains it
 249728    public Catalog Catalog { get; internal set; }
 29
 30    // protected internal no-parm constructor required for deserialization
 91231    protected internal BaseModelClass()
 32    {
 91233    }
 34
 35    [SetsRequiredMembers]
 105036    protected BaseModelClass(Catalog catalog)
 37    {
 105038        Catalog = catalog;
 105039        Type = Naming.SpdxTypeForClass(GetType());
 105040        SpdxId = catalog.NewId(GetType());
 105041        catalog.Items[SpdxId] = this;
 105042    }
 43
 44
 45    public virtual void Validate()
 46    {
 19147        ValidateRequiredProperty(nameof(SpdxId));
 15748        ValidateRequiredProperty(nameof(Type));
 15449    }
 50
 51    protected void ValidateRequiredProperty(string propertyName)
 52    {
 1424453        var props = GetType().GetProperties().Where(p => p.Name == propertyName).ToList();
 75954        PropertyInfo? propertyInfo = null;
 55
 75956        if (props.Count > 1)
 57        {
 958            propertyInfo = props.Single(p => p.GetCustomAttribute<RequiredMemberAttribute>() != null);
 59        }
 60        else
 61        {
 75662            propertyInfo = props.FirstOrDefault();
 63        }
 64
 75965        if (propertyInfo == null)
 66        {
 167            throw new Spdx3ValidationException(this, $"'{propertyName}'", "No such property exists");
 68        }
 69
 75870        var propVal = propertyInfo.GetValue(this);
 71
 75872        switch (propVal)
 73        {
 74            case null:
 4275                throw new Spdx3ValidationException(this, propertyName, "Field is required");
 31676            case string when propVal.ToString() == string.Empty:
 877                throw new Spdx3ValidationException(this, propertyName, "String field is empty");
 78            case IList { Count: 0 }:
 179                throw new Spdx3ValidationException(this, propertyName, "List is empty");
 80        }
 70481    }
 82}