< Summary - pva.SuperV

Information
Class: pva.SuperV.Engine.WipProject
Assembly: pva.SuperV.Engine
File(s): /home/runner/work/pva.SuperV/pva.SuperV/pva.SuperV.Engine/WipProject.cs
Tag: dotnet-ubuntu_22190969454
Line coverage
93%
Covered lines: 181
Uncovered lines: 13
Coverable lines: 194
Total lines: 382
Line coverage: 93.2%
Branch coverage
78%
Covered branches: 36
Total branches: 46
Branch coverage: 78.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_ToLoadInstances()100%11100%
.ctor()100%11100%
.ctor(...)100%11100%
.ctor(...)100%11100%
CloneAsRunnable()100%11100%
Unload()100%11100%
AddClass(...)100%22100%
AddClass(...)75%4477.77%
UpdateClass(...)50%7675%
RemoveClass(...)100%22100%
AddField(...)100%11100%
AddField(...)100%22100%
UpdateField(...)50%22100%
RemoveField(...)100%11100%
AddFieldFormatter(...)100%22100%
UpdateFieldFormatter(...)50%4481.81%
RemoveFieldFormatter(...)100%11100%
VerifyFieldFormatterNotUsed(...)100%66100%
AddFieldChangePostProcessing(...)100%11100%
UpdateFieldChangePostProcessing(...)100%11100%
RemoveFieldChangePostProcessing(...)100%11100%
GetId()100%11100%
AddHistoryRepository(...)100%22100%
UpdateHistoryRepository(...)100%22100%
RemoveHistoryRepository(...)100%11100%
VerifyHistoryRepositoryNotUsed(...)100%66100%
AddScript(...)50%2266.66%
UpdateScript(...)50%2266.66%
RemoveScript(...)50%2266.66%

File(s)

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

#LineLine coverage
 1using pva.Helpers.Extensions;
 2using pva.SuperV.Engine.Exceptions;
 3using pva.SuperV.Engine.FieldFormatters;
 4using pva.SuperV.Engine.HistoryStorage;
 5using pva.SuperV.Engine.Processing;
 6
 7namespace pva.SuperV.Engine
 8{
 9    /// <summary>
 10    /// WIP (Work In Progress) project. It allows adding/changing/removing <see cref="Class"/>, <see cref="FieldDefiniti
 11    /// </summary>
 12    /// <seealso cref="pva.SuperV.Engine.Project" />
 13    public class WipProject : Project
 14    {
 15        private const string ClassEntityType = "Class";
 16
 17        /// <summary>
 18        /// To be loaded instances when the project is converted to a <see cref="RunnableProject"/> through <see cref="P
 19        /// </summary>
 100120        public Dictionary<string, Instance> ToLoadInstances { get; } = new(StringComparer.OrdinalIgnoreCase);
 21
 22        /// <summary>
 23        /// Initializes a new instance of the <see cref="WipProject"/> class. Only used for deserialization.
 24        /// </summary>
 125        public WipProject()
 126        {
 127        }
 28
 29        /// <summary>
 30        /// Initializes a new instance of the <see cref="WipProject"/> class.
 31        /// </summary>
 32        /// <param name="projectName">Name of the project.</param>
 25233        public WipProject(string projectName)
 25234        {
 25235            Name = projectName;
 24936            Version = GetNextVersion();
 24937        }
 38
 39        /// <summary>
 40        /// Initializes a new instance of the <see cref="WipProject"/> class from a <see cref="RunnableProject"/>.
 41        /// </summary>
 42        /// <param name="runnableProject">The runnable project.</param>
 3843        public WipProject(RunnableProject runnableProject)
 3844        {
 3845            Name = runnableProject.Name;
 3846            Description = runnableProject.Description;
 3847            Version = GetNextVersion();
 3848            Classes = new(runnableProject.Classes.Count);
 3849            runnableProject.Classes
 19050                .ForEach((k, v) => Classes.Add(k, v.Clone()));
 3851            FieldFormatters = new(runnableProject.FieldFormatters);
 3852            HistoryStorageEngineConnectionString = runnableProject.HistoryStorageEngineConnectionString;
 3853            HistoryStorageEngine = HistoryStorageEngineFactory.CreateHistoryStorageEngine(runnableProject.HistoryStorage
 3854            HistoryRepositories = new(runnableProject.HistoryRepositories);
 3855            HistoryRepositories.Values.ForEach(repository
 7656                => repository.HistoryStorageEngine = HistoryStorageEngine);
 3857            TopicsChannels = new(runnableProject.TopicsChannels);
 3858            ToLoadInstances = new(runnableProject.Instances, StringComparer.OrdinalIgnoreCase);
 3859        }
 60
 61        /// <summary>
 62        /// Clones as <see cref="RunnableProject"/>.
 63        /// </summary>
 64        /// <returns><see cref="RunnableProject"/></returns>
 65        public RunnableProject CloneAsRunnable()
 13466            => new(this);
 67
 68        /// <summary>
 69        /// Unloads the project.
 70        /// </summary>
 71        public override void Unload()
 28772        {
 29073            ToLoadInstances.Values.ForEach(instance => instance.Dispose());
 28774            ToLoadInstances.Clear();
 28775            base.Unload();
 28776        }
 77
 78        /// <summary>
 79        /// Adds a new class to the project.
 80        /// </summary>
 81        /// <param name="className">Name of the class.</param>
 82        /// <returns>The newly created <see cref="Class"/>.</returns>
 83        /// <exception cref="pva.SuperV.Engine.Exceptions.EntityAlreadyExistException"></exception>
 84        public Class AddClass(string className)
 54685        {
 54686            if (Classes.ContainsKey(className))
 187            {
 188                throw new EntityAlreadyExistException(ClassEntityType, className);
 89            }
 90
 54591            Class clazz = new(className);
 54592            Classes.Add(className, clazz);
 54593            return clazz;
 54594        }
 95
 96        /// <summary>
 97        /// Adds a new class with inheritance to the project.
 98        /// </summary>
 99        /// <param name="className">Name of the class.</param>
 100        /// <param name="baseClassName">Name of the base class.</param>
 101        /// <returns>The newly created <see cref="Class"/>.</returns>
 102        /// <exception cref="pva.SuperV.Engine.Exceptions.EntityAlreadyExistException"></exception>
 103        public Class AddClass(string className, string? baseClassName)
 161104        {
 161105            Class? baseClass = baseClassName is null ? null : GetClass(baseClassName);
 161106            if (Classes.ContainsKey(className))
 0107            {
 0108                throw new EntityAlreadyExistException(ClassEntityType, className);
 109            }
 110
 161111            Class clazz = new(className, baseClass);
 161112            Classes.Add(className, clazz);
 161113            return clazz;
 161114        }
 115
 116        /// <summary>
 117        /// Updates a class.
 118        /// </summary>
 119        /// <param name="className">Name of class to be updated</param>
 120        /// <param name="baseClassName">Base class name</param>
 121        /// <returns>Updated class.</returns>
 122        /// <exception cref="UnknownEntityException"></exception>
 123        public Class UpdateClass(string className, string? baseClassName)
 1124        {
 1125            if (Classes.TryGetValue(className, out Class? clazz))
 1126            {
 1127                Class? baseClass = null;
 1128                if (!String.IsNullOrEmpty(baseClassName) && !Classes.TryGetValue(className, out baseClass))
 0129                {
 0130                    throw new UnknownEntityException(ClassEntityType, baseClassName);
 131                }
 1132                clazz.BaseClassName = baseClassName;
 1133                clazz.BaseClass = baseClass;
 1134                return clazz;
 135            }
 0136            throw new UnknownEntityException(ClassEntityType, className);
 1137        }
 138
 139        /// <summary>
 140        /// Removes a class from project.
 141        /// </summary>
 142        /// <param name="className">Name of the class.</param>
 143        public void RemoveClass(string className)
 3144        {
 3145            if (Classes.Remove(className, out var clazz))
 2146            {
 2147                ToLoadInstances.Values
 1148                    .Where(instance => instance.Class.Name!.Equals(clazz.Name))
 2149                    .ToList()
 3150                    .ForEach(instance => ToLoadInstances.Remove(instance.Name));
 2151            }
 3152        }
 153
 154        /// <summary>
 155        /// Adds a field to a class.
 156        /// </summary>
 157        /// <param name="className">Name of the class.</param>
 158        /// <param name="field">The field.</param>
 159        /// <returns>Added field</returns>
 160        public IFieldDefinition AddField(string className, IFieldDefinition field)
 1278161        {
 1278162            Class clazz = GetClass(className);
 1278163            IFieldDefinition fieldDefinition = clazz.AddField(field);
 1277164            SetFieldValueChangeChannel(fieldDefinition);
 1277165            return fieldDefinition;
 1277166        }
 167        /// <summary>
 168        /// Adds a field to a class with a specific field formatter.
 169        /// </summary>
 170        /// <param name="className">Name of the class.</param>
 171        /// <param name="field">The field.</param>
 172        /// <param name="formatterName">Name of the formatter.</param>
 173        /// <returns>Added field</returns>
 174        public IFieldDefinition AddField(string className, IFieldDefinition field, string? formatterName)
 2202175        {
 2202176            Class clazz = GetClass(className);
 2202177            FieldFormatter? formatter = GetFormatter(formatterName);
 2201178            formatter?.ValidateAllowedType(field.Type);
 2200179            IFieldDefinition fieldDefinition = clazz.AddField(field, formatter);
 2200180            SetFieldValueChangeChannel(fieldDefinition);
 2200181            return fieldDefinition;
 2200182        }
 183
 184        public IFieldDefinition UpdateField(string className, string fieldName, IFieldDefinition field, string? formatte
 4185        {
 4186            Class clazz = GetClass(className);
 4187            FieldFormatter? formatter = GetFormatter(formatterName);
 4188            formatter?.ValidateAllowedType(field.Type);
 4189            IFieldDefinition fieldDefinition = clazz.UpdateField(fieldName, field, formatter);
 2190            SetFieldValueChangeChannel(fieldDefinition);
 2191            return fieldDefinition;
 2192        }
 193
 194        /// <summary>
 195        /// Removes a field from a class.
 196        /// </summary>
 197        /// <param name="className">Name of the class.</param>
 198        /// <param name="fieldName">Name of the field.</param>
 199        public void RemoveField(string className, string fieldName)
 2200        {
 2201            Class clazz = GetClass(className);
 2202            clazz.RemoveField(fieldName);
 1203        }
 204
 205        /// <summary>
 206        /// Adds a field formatter to project to be later used for a specific field formatting (<see cref="AddField{T}(s
 207        /// </summary>
 208        /// <param name="fieldFormatter">The field formatter.</param>
 209        /// <exception cref="pva.SuperV.Engine.Exceptions.EntityAlreadyExistException"></exception>
 210        public void AddFieldFormatter(FieldFormatter fieldFormatter)
 212211        {
 212212            if (FieldFormatters.ContainsKey(fieldFormatter.Name!))
 1213            {
 1214                throw new EntityAlreadyExistException("Field formatter", fieldFormatter.Name);
 215            }
 216
 211217            FieldFormatters.Add(fieldFormatter.Name!, fieldFormatter);
 211218        }
 219
 220        public void UpdateFieldFormatter(string fieldFormatterName, FieldFormatter fieldFormatter)
 2221        {
 2222            FieldFormatter? existingFormatter = GetFormatter(fieldFormatterName);
 2223            if (existingFormatter != null)
 2224            {
 2225                if (existingFormatter.GetType() == fieldFormatter.GetType())
 2226                {
 2227                    FieldFormatters[fieldFormatterName] = fieldFormatter;
 2228                    return;
 229                }
 0230                throw new WrongFieldTypeException(fieldFormatterName, existingFormatter.GetType(), fieldFormatter.GetTyp
 231            }
 0232            throw new UnknownEntityException("Field formatter", fieldFormatterName);
 2233        }
 234
 235
 236        /// <summary>
 237        /// Removes a field formatter.
 238        /// </summary>
 239        /// <param name="fieldFormatterName">Name of the field formatter.</param>
 240        public bool RemoveFieldFormatter(string fieldFormatterName)
 5241        {
 5242            VerifyFieldFormatterNotUsed(fieldFormatterName);
 3243            return FieldFormatters.Remove(fieldFormatterName);
 3244        }
 245
 246        private void VerifyFieldFormatterNotUsed(string fieldFormatterName)
 5247        {
 5248            Classes.Values.ForEach(clazz =>
 11249            {
 11250                List<String> fieldsUsingFormatter = [.. clazz.FieldDefinitions.Values
 52251                    .Where(field => field.Formatter?.Name.Equals(fieldFormatterName) == true)
 13252                    .Select(field => field.Name)];
 11253                if (fieldsUsingFormatter.Count > 0)
 2254                {
 2255                    throw new EntityInUseException("Field formatter", fieldFormatterName, clazz.Name, fieldsUsingFormatt
 5256                }
 14257            });
 3258        }
 259
 260        /// <summary>
 261        /// Adds a field change post processing on a field..
 262        /// </summary>
 263        /// <param name="className">Name of the class.</param>
 264        /// <param name="fieldName">Name of the field.</param>
 265        /// <param name="fieldValueProcessing">The field value processing.</param>
 266        public void AddFieldChangePostProcessing(string className, string fieldName, IFieldValueProcessing fieldValuePro
 2377267        {
 2377268            Class clazz = GetClass(className);
 2377269            clazz.AddFieldChangePostProcessing(fieldName, fieldValueProcessing);
 2377270        }
 271
 272        public void UpdateFieldChangePostProcessing(string className, string fieldName, string processingName, IFieldVal
 1273        {
 1274            Class clazz = GetClass(className);
 1275            clazz.UpdateFieldChangePostProcessing(fieldName, processingName, fieldProcessing);
 1276        }
 277
 278        public void RemoveFieldChangePostProcessing(string className, string fieldName, string processingName)
 1279        {
 1280            Class clazz = GetClass(className);
 1281            clazz.RemoveFieldChangePostProcessing(fieldName, processingName);
 1282        }
 283
 284        public override string GetId()
 1037285        {
 1037286            return $"{Name!}-WIP";
 1037287        }
 288
 289        /// <summary>
 290        /// Adds a history repository to project./>.
 291        /// </summary>
 292        /// <param name="historyRepository">The history repository.</param>
 293        /// <exception cref="pva.SuperV.Engine.Exceptions.EntityAlreadyExistException"></exception>
 294        public void AddHistoryRepository(HistoryRepository historyRepository)
 168295        {
 168296            if (HistoryRepositories.ContainsKey(historyRepository.Name))
 1297            {
 1298                throw new EntityAlreadyExistException("History repository", historyRepository.Name);
 299            }
 300
 167301            historyRepository.HistoryStorageEngine = HistoryStorageEngine;
 167302            HistoryRepositories.Add(historyRepository.Name, historyRepository);
 167303        }
 304
 305        public void UpdateHistoryRepository(string historyRepositoryName, HistoryRepository historyRepository)
 2306        {
 2307            if (HistoryRepositories.TryGetValue(historyRepositoryName, out HistoryRepository? _))
 1308            {
 1309                HistoryRepositories[historyRepositoryName] = historyRepository;
 1310                return;
 311            }
 1312            throw new UnknownEntityException("History repository", historyRepositoryName);
 1313        }
 314
 315        /// <summary>
 316        /// Removes a history repository.
 317        /// </summary>
 318        /// <param name="historyRepositoryName">Name of the history repository.</param>
 319        public void RemoveHistoryRepository(string historyRepositoryName)
 3320        {
 3321            VerifyHistoryRepositoryNotUsed(historyRepositoryName);
 2322            HistoryRepositories.Remove(historyRepositoryName);
 2323        }
 324
 325        private void VerifyHistoryRepositoryNotUsed(string historyRepositoryName)
 3326        {
 3327            Classes.Values.ForEach(clazz =>
 6328            {
 6329                List<String> fieldsUsingHistoryRepository = [.. clazz.FieldDefinitions.Values
 29330                    .Where(field => field.ValuePostChangeProcessings
 29331                        .OfType<IHistorizationProcessing>()
 30332                        .Any(historyValueProcessing => historyValueProcessing.IsUsingRepository(historyRepositoryName)))
 7333                    .Select(field => field.Name)];
 6334                if (fieldsUsingHistoryRepository.Count > 0)
 1335                {
 1336                    throw new EntityInUseException("History Repository", historyRepositoryName, clazz.Name, fieldsUsingH
 3337                }
 8338            });
 2339        }
 340
 341        /// <summary>
 342        /// Adds a script definition.
 343        /// </summary>
 344        /// <param name="script">The script.</param>
 345        /// <exception cref="EntityAlreadyExistException">Script</exception>
 346        public void AddScript(ScriptDefinition script)
 160347        {
 160348            if (ScriptDefinitions.ContainsKey(script.Name))
 0349            {
 0350                throw new EntityAlreadyExistException("Script", script.Name);
 351            }
 160352            ScriptDefinitions.Add(script.Name, script);
 160353        }
 354
 355        /// <summary>
 356        /// Updates a script definition.
 357        /// </summary>
 358        /// <param name="script">The script.</param>
 359        /// <exception cref="UnknownEntityException">Script</exception>
 360        public void UpdateScript(ScriptDefinition script)
 1361        {
 1362            if (!ScriptDefinitions.ContainsKey(script.Name))
 0363            {
 0364                throw new UnknownEntityException("Script", script.Name);
 365            }
 1366            ScriptDefinitions[script.Name] = script;
 1367        }
 368        /// <summary>
 369        /// Removes a script definition.
 370        /// </summary>
 371        /// <param name="scriptName">The script name.</param>
 372        /// <exception cref="UnknownEntityException">Script</exception>
 373        public void RemoveScript(string scriptName)
 1374        {
 1375            if (!ScriptDefinitions.ContainsKey(scriptName))
 0376            {
 0377                throw new UnknownEntityException("Script", scriptName);
 378            }
 1379            ScriptDefinitions.Remove(scriptName);
 1380        }
 381    }
 382}