< Summary - pva.SuperV

Information
Class: pva.SuperV.Engine.Project
Assembly: pva.SuperV.Engine
File(s): /home/runner/work/pva.SuperV/pva.SuperV/pva.SuperV.Engine/Project.cs
Tag: dotnet-ubuntu_18869653307
Line coverage
99%
Covered lines: 127
Uncovered lines: 1
Coverable lines: 128
Total lines: 349
Line coverage: 99.2%
Branch coverage
95%
Covered branches: 23
Total branches: 24
Branch coverage: 95.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_ProjectsPath()100%11100%
get_CurrentProject()100%210%
get_Name()100%11100%
set_Name(...)100%11100%
get_Description()100%11100%
get_Version()100%11100%
get_Classes()100%11100%
get_FieldFormatters()100%11100%
get_HistoryStorageEngineConnectionString()100%11100%
get_HistoryStorageEngine()100%11100%
set_HistoryStorageEngine(...)100%11100%
get_HistoryRepositories()100%11100%
get_Projects()100%11100%
CreateProject(...)100%11100%
CreateProject(...)100%22100%
CreateProject(...)100%11100%
AddProjectToCollection(...)100%44100%
BuildAsync()100%11100%
GetClass(...)100%22100%
FindClass(...)100%11100%
GetFormatter(...)100%44100%
FindFormatter(...)100%11100%
GetAssemblyFileName()100%22100%
GetProjectHighestVersion(...)100%22100%
GetNextVersion()100%11100%
Unload(...)100%44100%
Unload()100%11100%
CallGcCleanup(...)75%44100%
Dispose()100%11100%
Dispose(...)100%11100%

File(s)

/home/runner/work/pva.SuperV/pva.SuperV/pva.SuperV.Engine/Project.cs

#LineLine coverage
 1using pva.Helpers.Extensions;
 2using pva.SuperV.Engine.Exceptions;
 3using pva.SuperV.Engine.FieldFormatters;
 4using pva.SuperV.Engine.HistoryStorage;
 5using System.Collections.Concurrent;
 6using System.Text.Json.Serialization;
 7
 8namespace pva.SuperV.Engine
 9{
 10    /// <summary>
 11    /// SuperV Project class. It contains all the information required (<see cref="Class"/>, <see cref="Instance"/>, pro
 12    /// </summary>
 13    public abstract class Project : IDisposable
 14    {
 15        /// <summary>
 16        /// Gets the projects path where all SuperV stuff is stored (generated assemblies, project definitions and snaps
 17        /// </summary>
 18        /// <value>
 19        /// The projects path.
 20        /// </value>
 1581921        public static string ProjectsPath { get; } = Path.Combine(Path.GetTempPath(), "pva.SuperV");
 22
 23        /// <summary>
 24        /// Gets or sets the current project.
 25        /// </summary>
 26        /// <value>
 27        /// The current project.
 28        /// </value>
 029        public static Project? CurrentProject { get; set; }
 30
 31        /// <summary>
 32        /// The name of project. Use <see cref="Name"/> to access its content.
 33        /// </summary>
 34        private string? _name;
 35
 36        /// <summary>
 37        /// Gets or sets the name of the project.
 38        /// </summary>
 39        /// <value>
 40        /// The project name.
 41        /// </value>
 42        public string? Name
 43        {
 370444            get => _name;
 45            set
 41546            {
 41547                IdentifierValidation.ValidateIdentifier("project", value);
 41248                _name = value;
 41249            }
 50        }
 51
 52        /// <summary>
 53        /// Gets or sets the description.
 54        /// </summary>
 55        /// <value>
 56        /// The description.
 57        /// </value>
 36758        public string? Description { get; set; }
 59
 60        /// <summary>
 61        /// Gets or sets the version.
 62        /// </summary>
 63        /// <value>
 64        /// The version.
 65        /// </value>
 206866        public int Version { get; set; }
 67
 68        /// <summary>
 69        /// Gets the classes of project.
 70        /// </summary>
 71        /// <value>
 72        /// The classes.
 73        /// </value>
 626574        public Dictionary<string, Class> Classes { get; init; } = new(StringComparer.OrdinalIgnoreCase);
 75
 76        /// <summary>
 77        /// Gets the field formatters.
 78        /// </summary>
 79        /// <value>
 80        /// The field formatters.
 81        /// </value>
 190382        public Dictionary<string, FieldFormatter> FieldFormatters { get; init; } = new(StringComparer.OrdinalIgnoreCase)
 83
 84        private IHistoryStorageEngine? historyStorageEngine;
 85
 86        /// <summary>
 87        /// The history storage engin connection string.
 88        /// </summary>
 68389        public string? HistoryStorageEngineConnectionString { get; set; }
 90
 91        /// <summary>
 92        /// Gets the history repositories.
 93        /// </summary>
 94        /// <value>
 95        /// The history repositories.
 96        /// </value>
 97        [JsonIgnore]
 98        public IHistoryStorageEngine? HistoryStorageEngine
 99        {
 591100            get => historyStorageEngine;
 101            set
 359102            {
 359103                historyStorageEngine = value;
 360104                HistoryRepositories.Values.ForEach(historyRepository => historyRepository.HistoryStorageEngine = history
 359105            }
 106        }
 107
 108        /// <summary>
 109        /// Gets the history repositories.
 110        /// </summary>
 111        /// <value>
 112        /// The history repositories.
 113        /// </value>
 2020114        public Dictionary<string, HistoryRepository> HistoryRepositories { get; init; } = new(StringComparer.OrdinalIgno
 115
 116        /// <summary>
 117        /// List of projects in use.
 118        /// </summary>
 1762119        public static ConcurrentDictionary<string, Project> Projects { get; } = new(StringComparer.OrdinalIgnoreCase);
 120
 121        /// <summary>
 122        /// Creates an empty <see cref="WipProject"/>.
 123        /// </summary>
 124        /// <param name="projectName">Name of the project.</param>
 125        /// <returns>The created <see cref="WipProject"/></returns>
 126        public static WipProject CreateProject(string projectName)
 92127        {
 92128            return CreateProject(projectName, null);
 89129        }
 130
 131        /// <summary>
 132        /// Creates an empty <see cref="WipProject"/>.
 133        /// </summary>
 134        /// <param name="projectName">Name of the project.</param>
 135        /// <param name="historyStorageEngineConnectionString">History storage connection string.</param>
 136        /// <returns>The created <see cref="WipProject"/></returns>
 137        public static WipProject CreateProject(string projectName, string? historyStorageEngineConnectionString)
 239138        {
 239139            WipProject project = new(projectName);
 236140            AddProjectToCollection(project);
 236141            if (string.IsNullOrEmpty(historyStorageEngineConnectionString))
 91142            {
 91143                return project;
 144            }
 145
 145146            project.HistoryStorageEngineConnectionString = historyStorageEngineConnectionString;
 145147            project.HistoryStorageEngine = HistoryStorageEngineFactory.CreateHistoryStorageEngine(historyStorageEngineCo
 145148            return project;
 236149        }
 150
 151        /// <summary>
 152        /// Creates a <see cref="WipProject"/> from a <see cref="RunnableProject"/> for modification.
 153        /// </summary>
 154        /// <param name="runnableProject">The runnable project from which to create the new <see cref="WipProject"/>.</p
 155        /// <returns>The new <see cref="WipProject"/></returns>
 156        public static WipProject CreateProject(RunnableProject runnableProject)
 36157        {
 36158            WipProject wipProject = new(runnableProject);
 36159            AddProjectToCollection(wipProject);
 36160            return wipProject;
 36161        }
 162
 163        internal static void AddProjectToCollection(Project project)
 410164        {
 410165            if (Projects.TryGetValue(project.GetId(), out Project? previousProject))
 47166            {
 47167                previousProject?.Unload();
 47168            }
 410169            Projects[project.GetId()] = project;
 410170        }
 171
 172        /// <summary>
 173        /// Builds the specified <see cref="WipProject"/>.
 174        /// </summary>
 175        /// <param name="wipProject">The WIP project.</param>
 176        /// <returns>a <see cref="RunnableProject"/></returns>
 177        public static async Task<RunnableProject> BuildAsync(WipProject wipProject)
 126178        {
 126179            RunnableProject runnableProject = await ProjectBuilder.BuildAsync(wipProject);
 124180            AddProjectToCollection(runnableProject);
 124181            return runnableProject;
 124182        }
 183
 184        /// <summary>
 185        /// Gets a class for a name.
 186        /// </summary>
 187        /// <param name="className">Name of the class.</param>
 188        /// <returns>Found class</returns>
 189        /// <exception cref="pva.SuperV.Engine.Exceptions.UnknownClassException"></exception>
 190        public Class GetClass(string className)
 3587191        {
 3587192            if (Classes.TryGetValue(className, out Class? value))
 3585193            {
 3585194                return value;
 195            }
 196
 2197            throw new UnknownEntityException("Class", className);
 3585198        }
 199
 200        /// <summary>
 201        /// Finds a class for a name.
 202        /// </summary>
 203        /// <param name="className">Name of the class.</param>
 204        /// <returns><see cref="Class"/> if found or null otherwise.</returns>
 205        public Class? FindClass(string className)
 2206        {
 207            try
 2208            {
 2209                return GetClass(className);
 210            }
 3211            catch { return null; }
 2212        }
 213
 214        /// <summary>
 215        /// Gets a formatter for name.
 216        /// </summary>
 217        /// <param name="formatterName">Name of the formatter.</param>
 218        /// <returns><see cref="FieldFormatter"/></returns>
 219        /// <exception cref="pva.SuperV.Engine.Exceptions.UnknownFormatterException"></exception>
 220        public FieldFormatter? GetFormatter(string? formatterName)
 308221        {
 308222            if (String.IsNullOrEmpty(formatterName))
 4223            {
 4224                return null;
 225            }
 304226            if (FieldFormatters.TryGetValue(formatterName, out FieldFormatter? value))
 299227            {
 299228                return value;
 229            }
 230
 5231            throw new UnknownEntityException("Field formatter", formatterName);
 303232        }
 233
 234        /// <summary>
 235        /// Finds a formatter for name.
 236        /// </summary>
 237        /// <param name="formatterName">Name of the formatter.</param>
 238        /// <returns><see cref="FieldFormatter"/> if found or null otherwise.</returns>
 239        public FieldFormatter? FindFormatter(string formatterName)
 2240        {
 241            try
 2242            {
 2243                return GetFormatter(formatterName);
 244            }
 3245            catch { return null; }
 2246        }
 247
 248        /// <summary>
 249        /// Gets the name of the generated assembly file for project.
 250        /// </summary>
 251        /// <returns>Assembly file name</returns>
 252        public string GetAssemblyFileName()
 654253        {
 654254            if (!Directory.Exists(ProjectsPath))
 1255            {
 1256                Directory.CreateDirectory(ProjectsPath);
 1257            }
 654258            return Path.Combine(ProjectsPath, $"{Name}-V{Version}.dll");
 654259        }
 260
 261        /// <summary>
 262        /// Gets the project highest version from generated assemblies of project.
 263        /// </summary>
 264        /// <param name="projectName">Name of the project.</param>
 265        /// <returns>The highest version or 0 if first version.</returns>
 266        protected static int GetProjectHighestVersion(string projectName)
 272267        {
 272268            return Directory.Exists(ProjectsPath)
 272269                ? Directory.EnumerateFiles(ProjectsPath, $"{projectName}-V*.dll")
 272270                    .Select(fileName =>
 13938271                    Convert.ToInt32(fileName
 13938272                        .Replace(ProjectsPath, "")
 13938273                        .Replace(Path.DirectorySeparatorChar.ToString(), "")
 13938274                        .Replace($"{projectName}-V", "")
 13938275                        .Replace(".dll", "")))
 272276                    .Order()
 272277                    .LastOrDefault()
 272278                : 0;
 272279        }
 280
 281        /// <summary>
 282        /// Gets the next version for project.
 283        /// </summary>
 284        /// <returns>Next project version</returns>
 285        protected int GetNextVersion()
 272286        {
 272287            return GetProjectHighestVersion(Name!) + 1;
 272288        }
 289
 290        /// <summary>
 291        /// Unloads the project.
 292        /// </summary>
 293        public static void Unload(Project project)
 13294        {
 13295            WeakReference? projectAssemblyLoaderWeakRef = null;
 13296            if (project is RunnableProject runnableProject)
 13297            {
 13298                projectAssemblyLoaderWeakRef = runnableProject.ProjectAssemblyLoaderWeakRef;
 13299            }
 13300            project.Dispose();
 13301            if (projectAssemblyLoaderWeakRef is not null)
 13302            {
 13303                CallGcCleanup(projectAssemblyLoaderWeakRef);
 13304            }
 13305        }
 306
 307
 308        /// <summary>
 309        /// Unloads the project.
 310        /// </summary>
 311        public virtual void Unload()
 408312        {
 408313            FieldFormatters.Clear();
 408314            Classes.Clear();
 408315            Projects.Remove(GetId(), out _);
 408316        }
 317
 318        [System.Diagnostics.CodeAnalysis.SuppressMessage("Critical Code Smell", "S1215:\"GC.Collect\" should not be call
 319            Justification = "Need to call GC to remove references to assembly")]
 320        public static void CallGcCleanup(WeakReference palWeakRef)
 13321        {
 286322            for (int i = 0; palWeakRef.IsAlive && i < 10; i++)
 130323            {
 130324                GC.Collect();
 130325                GC.WaitForPendingFinalizers();
 130326            }
 13327        }
 328
 329        /// <summary>
 330        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 331        /// </summary>
 332        public void Dispose()
 360333        {
 360334            Dispose(true);
 360335            GC.SuppressFinalize(this);
 360336        }
 337
 338        /// <summary>
 339        /// Releases unmanaged and - optionally - managed resources.
 340        /// </summary>
 341        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release
 342        protected virtual void Dispose(bool disposing)
 360343        {
 360344            Unload();
 360345        }
 346
 347        public abstract string GetId();
 348    }
 349}