< Summary

Information
Class: Spdx3.Utility.Catalog
Assembly: Spdx3
File(s): /home/runner/work/Spdx3/Spdx3/Spdx3/Utility/Catalog.cs
Line coverage
95%
Covered lines: 46
Uncovered lines: 2
Coverable lines: 48
Total lines: 195
Line coverage: 95.8%
Branch coverage
94%
Covered branches: 32
Total branches: 34
Branch coverage: 94.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor()100%11100%
get_Items()100%11100%
NewId(...)100%11100%
GetSpdxDocument()50%2280%
GetModel()100%11100%
GetShortUid()100%11100%
AssembleSpdxDocument()100%44100%
ReplacePlaceHoldersWithRealObjects()100%66100%
RehydratePlaceHolderWithRealItem(...)75%4485.71%
GetItems()100%22100%
GetRelationshipsFromTo()100%88100%
GetRelationshipsFromTo(...)100%44100%
GetRelationshipsFrom(...)100%11100%
GetRelationshipsFrom()100%22100%
GetRelationshipsTo(...)100%11100%
GetRelationshipsTo()100%22100%
GetRelationshipsOfType(...)100%11100%

File(s)

/home/runner/work/Spdx3/Spdx3/Spdx3/Utility/Catalog.cs

#LineLine coverage
 1using System.Reflection;
 2using Spdx3.Exceptions;
 3using Spdx3.Model;
 4using Spdx3.Model.Core.Classes;
 5using Spdx3.Model.Core.Enums;
 6
 7namespace Spdx3.Utility;
 8
 9/// <summary>
 10///     A class that tracks objects created and helps make ID's for new objets.
 11/// </summary>
 12public class Catalog
 13{
 14    private long _idCounter;
 15
 22016    public Catalog(int startCounterAt)
 17    {
 22018        _idCounter = startCounterAt;
 22019    }
 20
 1921    public Catalog()
 22    {
 1923        _idCounter = DateTime.Now.Ticks - (new DateTime(2025,1,1,0,0,0) ).Ticks;
 1924    }
 25
 26
 27    // A running list of all the objects created
 147928    public IDictionary<Uri, BaseModelClass> Items { get; } = new Dictionary<Uri, BaseModelClass>();
 29
 30    /// <summary>
 31    ///     There's no semantic meaning to an SPDX ID, and no real correspondence to real life objects.
 32    ///     It's just an element identifier used within the document, so things can reference each other.
 33    /// </summary>
 34    /// <param name="type">The type of object to create an ID for</param>
 35    /// <returns>A URN that can be used as a node identifier (spdxId)</returns>
 36    public Uri NewId(Type type)
 37    {
 105438        return new Uri($"urn:{type.Name}:{GetShortUid()}");
 39    }
 40
 41    /// <summary>
 42    ///     Get the one SpdxDocument object from the catalog
 43    /// </summary>
 44    /// <returns>The one SpdxDocument</returns>
 45    /// <exception cref="Spdx3Exception">If not exactly one SpdxDocument could be found.</exception>
 46    public SpdxDocument GetSpdxDocument()
 47    {
 248        var spdxDocs = GetItems<SpdxDocument>();
 49
 250        if (spdxDocs.Count != 1)
 51        {
 052            throw new Spdx3Exception($"Expected exactly one SpdxDocument, but got {spdxDocs.Count}.");
 53        }
 54
 255        var result = spdxDocs.First();
 256        return result;
 57    }
 58
 59    /// <summary>
 60    ///     Reconstruct a model object graph from the flat list of items in the catalog
 61    /// </summary>
 62    /// <returns>The SpdxDocument that is the top-level element in the document</returns>
 63    /// <exception cref="Spdx3SerializationException">If there is not exactly one SpdxDocument element in the catalog</e
 64    public SpdxDocument GetModel()
 65    {
 266        ReplacePlaceHoldersWithRealObjects();
 267        return AssembleSpdxDocument();
 68    }
 69
 70    private string GetShortUid()
 71    {
 72        // add 13 each time so the numbers look more different from each other and don't look like an incrementing count
 105473        return (_idCounter += 13).ToString("x");
 74    }
 75
 76
 77    /// <summary>
 78    ///     Take all the rehydrated items in the catalog, and assemble them into an SpdxDocument object
 79    /// </summary>
 80    /// <returns>The assembled SpdxDocument from the catalog</returns>
 81    private SpdxDocument AssembleSpdxDocument()
 82    {
 283        var result = GetSpdxDocument();
 84
 11485        foreach (var baseModelClass in Items.Values.ToList())
 86        {
 5587            if (baseModelClass is Element e)
 88            {
 4589                result.Element.Add(e);
 90            }
 91        }
 92
 293        return result;
 94    }
 95
 96    /// <summary>
 97    ///     Replace all the placeholders in the Catalog items with references to real objects
 98    /// </summary>
 99    private void ReplacePlaceHoldersWithRealObjects()
 100    {
 114101        foreach (var item in Items.Values.ToList())
 102        {
 103            // Get the properties that are Spdx Model Class types and are not null
 55104            var props = item.GetType().GetProperties()
 925105                .Where(p => p.GetValue(item) != null && p.GetValue(item) is BaseModelClass);
 106
 220107            foreach (var prop in props)
 108            {
 55109                RehydratePlaceHolderWithRealItem(prop, item);
 110            }
 111        }
 2112    }
 113
 114    /// <summary>
 115    ///     Rehydrate a specific property (which has a placeholder value) on an object with the real object from the cat
 116    /// </summary>
 117    /// <param name="prop">The property that currently has a placeholder that needs replacing</param>
 118    /// <param name="itemWithProperty">The item that has the placeholder property</param>
 119    /// <exception cref="Spdx3Exception">If </exception>
 120    private void RehydratePlaceHolderWithRealItem(PropertyInfo prop, BaseModelClass itemWithProperty)
 121    {
 55122        var isSpdxClass = prop.PropertyType.IsAssignableTo(typeof(BaseModelClass));
 123
 55124        if (!isSpdxClass)
 125        {
 0126            return;
 127        }
 128
 55129        var placeHolder = prop.GetValue(itemWithProperty) as BaseModelClass;
 130#pragma warning disable CS8602 // Dereference of a possibly null reference.
 55131        if (Items.TryGetValue(placeHolder.SpdxId, out var value))
 132#pragma warning restore CS8602 // Dereference of a possibly null reference.
 133        {
 55134            prop.SetValue(itemWithProperty, value);
 135        }
 136
 55137    }
 138
 139    /// <summary>
 140    /// Get all the items in the catalog of type T
 141    /// </summary>
 142    /// <typeparam name="T">The type of items in the catalog you want</typeparam>
 143    /// <returns>The items in the catalog of type T as a List</returns>
 144    public List<T> GetItems<T>()
 145    {
 893146        return Items.Values.ToList().Where(x => x.GetType() == typeof(T)).Cast<T>().ToList();
 147    }
 148
 149    public List<Relationship> GetRelationshipsFromTo<TF, TT>()
 150    {
 4151        var relationships = GetItems<Relationship>();
 4152        var result = new List<Relationship>();
 153
 52154        foreach (var r in relationships.Where(r => r.From.GetType().IsAssignableTo(typeof(TF))))
 155        {
 22156            if (r.To.Any(t => t.GetType().IsAssignableFrom(typeof(TT))))
 157            {
 6158                result.Add(r);
 159            }
 160        }
 161
 4162        return result;
 163    }
 164
 165    public List<Relationship> GetRelationshipsFromTo(Element fromElement, Element toElement)
 166    {
 9167        return GetItems<Relationship>()
 76168            .Where(r => r.From.SpdxId == fromElement.SpdxId && r.To.Any(t => t.SpdxId == toElement.SpdxId)).ToList();
 169    }
 170
 171    public List<Relationship> GetRelationshipsFrom(Element fromElement)
 172    {
 42173        return GetItems<Relationship>().Where(r => r.From.SpdxId == fromElement.SpdxId).ToList();
 174    }
 175
 176    public List<Relationship> GetRelationshipsFrom<T>()
 177    {
 28178        return GetItems<Relationship>().Where(r => r.From.GetType().IsAssignableTo(typeof(T))).ToList();
 179    }
 180
 181    public List<Relationship> GetRelationshipsTo(Element toElement)
 182    {
 88183        return GetItems<Relationship>().Where(r => r.To.Select(x => x.SpdxId).Contains(toElement.SpdxId)).ToList();
 184    }
 185
 186    public List<Relationship> GetRelationshipsTo<T>()
 187    {
 58188        return GetItems<Relationship>().Where(r => r.To.Any(x => x.GetType() == typeof(T))).ToList();
 189    }
 190
 191    public List<Relationship> GetRelationshipsOfType(RelationshipType relType)
 192    {
 12193        return GetItems<Relationship>().Where(r => r.RelationshipType == relType).ToList();
 194    }
 195}