< Summary - pva.SuperV

Information
Class: pva.SuperV.Engine.Class
Assembly: pva.SuperV.Engine
File(s): /home/runner/work/pva.SuperV/pva.SuperV/pva.SuperV.Engine/Class.cs
Tag: dotnet-ubuntu_22190969454
Line coverage
93%
Covered lines: 109
Uncovered lines: 7
Coverable lines: 116
Total lines: 244
Line coverage: 93.9%
Branch coverage
75%
Covered branches: 21
Total branches: 28
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
get_Name()100%11100%
set_Name(...)100%11100%
get_BaseClass()100%11100%
get_BaseClassName()100%11100%
get_FieldDefinitions()100%11100%
.ctor(...)100%11100%
.ctor(...)100%22100%
AddField(...)100%11100%
AddField(...)100%22100%
UpdateField(...)50%2285.71%
GetField(...)75%4477.77%
GetField(...)50%2285.71%
RemoveField(...)100%11100%
AddFieldChangePostProcessing(...)100%11100%
UpdateFieldChangePostProcessing(...)50%4490.9%
RemoveFieldChangePostProcessing(...)50%4483.33%
VerifyFieldNotUsedInProcessings(...)100%66100%
GetCode()100%22100%
Clone()100%11100%

File(s)

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

#LineLine coverage
 1using pva.Helpers.Extensions;
 2using pva.SuperV.Engine.Exceptions;
 3using pva.SuperV.Engine.FieldFormatters;
 4using pva.SuperV.Engine.Processing;
 5using System.Text;
 6using System.Text.Json.Serialization;
 7
 8namespace pva.SuperV.Engine
 9{
 10    /// <summary>Dynamic class of a <see cref="Project"/>. It contains dynamic fields on which processing can be defined
 11    public class Class
 12    {
 13        private const string FieldEntityType = "Field";
 14
 15        /// <summary>
 16        /// Name of class. Access done through <see cref="Name"/>.
 17        /// </summary>
 89118        private string _name = string.Empty;
 19
 20        /// <summary>Gets or sets the name of the class.</summary>
 21        public string Name
 22        {
 1026023            get { return _name; }
 24            set
 89125            {
 89126                _name = IdentifierValidation.ValidateIdentifier("class", value);
 88827            }
 28        }
 29
 30        /// <summary>
 31        /// Gets or sets the base class.
 32        /// </summary>
 33        /// <value>
 34        /// The base class.
 35        /// </value>
 36        [JsonIgnore]
 173437        public Class? BaseClass { get; set; }
 38
 39        /// <summary>
 40        /// Gets or sets the name of the base class.
 41        /// </summary>
 42        /// <value>
 43        /// The name of the base class.
 44        /// </value>
 109245        public string? BaseClassName { get; set; }
 46
 47        /// <summary>Gets the fields defining the class.</summary>
 2078148        public Dictionary<string, IFieldDefinition> FieldDefinitions { get; set; } = new(StringComparer.OrdinalIgnoreCas
 49
 50        /// <summary>
 51        /// Initializes a new instance of the <see cref="Class"/> class. Used by JSON deserialization.
 52        /// </summary>
 1753        public Class()
 1754        {
 1755        }
 56
 57        /// <summary>
 58        /// Initializes a new instance of the <see cref="Class"/> class.
 59        /// </summary>
 60        /// <param name="className">Name of the class.</param>
 56161        public Class(string className) : this(className, null)
 55862        {
 55863        }
 64
 65        /// <summary>
 66        /// Initializes a new instance of the <see cref="Class"/> class with inheritance from a base class.
 67        /// </summary>
 68        /// <param name="className">Name of the class.</param>
 69        /// <param name="baseClass">Base class.</param>
 87470        public Class(string className, Class? baseClass)
 87471        {
 87472            this.Name = className;
 87173            this.BaseClass = baseClass;
 87174            this.BaseClassName = baseClass?.Name;
 87175        }
 76
 77        /// <summary>
 78        /// Adds a field definition to the class.
 79        /// </summary>
 80        /// <param name="field">The field.</param>
 81        /// <returns>The field once it has been added.</returns>
 82        public IFieldDefinition AddField(IFieldDefinition field)
 132983        {
 132984            return AddField(field, null);
 132885        }
 86
 87        /// <summary>
 88        /// Adds a field with a field formatter.
 89        /// </summary>
 90        /// <param name="field">The <see cref="FieldDefinition{T}"/> to be added.</param>
 91        /// <param name="formatter">The formatter to be used when using ToString()."/>.</param>
 92        /// <returns>Changed field definition</returns>
 93        /// <exception cref="pva.SuperV.Engine.Exceptions.EntityAlreadyExistException"></exception>
 94        public IFieldDefinition AddField(IFieldDefinition field, FieldFormatter? formatter)
 361195        {
 361196            if (FieldDefinitions.ContainsKey(field.Name))
 197            {
 198                throw new EntityAlreadyExistException(FieldEntityType, field.Name);
 99            }
 3610100            field.Formatter = formatter;
 3610101            FieldDefinitions.Add(field.Name, field);
 3610102            return field;
 3610103        }
 104
 105        public IFieldDefinition UpdateField(string fieldName, IFieldDefinition fieldDefinition, FieldFormatter? fieldFor
 4106        {
 4107            if (FieldDefinitions.TryGetValue(fieldName, out IFieldDefinition? fieldToUpdate))
 4108            {
 4109                fieldToUpdate.Update(fieldDefinition, fieldFormatter);
 2110                return fieldToUpdate;
 111            }
 0112            throw new UnknownEntityException(FieldEntityType, fieldName);
 2113        }
 114
 115        /// <summary>
 116        /// Gets a field.
 117        /// </summary>
 118        /// <param name="fieldName">Name of the field to be retrieved.</param>
 119        /// <returns>The field</returns>
 120        /// <exception cref="pva.SuperV.Engine.Exceptions.UnknownEntityException"></exception>
 121        public IFieldDefinition GetField(string fieldName)
 8062122        {
 8062123            if (FieldDefinitions.TryGetValue(fieldName, out IFieldDefinition? fieldDefinition))
 8061124            {
 8061125                return fieldDefinition;
 126            }
 1127            if (BaseClass is not null)
 0128            {
 0129                return BaseClass.GetField(fieldName);
 130            }
 1131            throw new UnknownEntityException(FieldEntityType, fieldName);
 8061132        }
 133
 134        /// <summary>
 135        /// Gets a field of a specific type.
 136        /// </summary>
 137        /// <typeparam name="T">Field type</typeparam>
 138        /// <param name="fieldName">Name of the field to be retrieved.</param>
 139        /// <returns>The field</returns>
 140        /// <exception cref="pva.SuperV.Engine.Exceptions.WrongFieldTypeException"></exception>
 141        /// <exception cref="pva.SuperV.Engine.Exceptions.UnknownEntityException"></exception>
 142        public FieldDefinition<T>? GetField<T>(string fieldName)
 3337143        {
 3337144            IFieldDefinition fieldDefinition = GetField(fieldName);
 3336145            if (fieldDefinition.Type == typeof(T))
 3336146            {
 3336147                return fieldDefinition as FieldDefinition<T>;
 148            }
 0149            throw new WrongFieldTypeException(fieldName, typeof(T), fieldDefinition.Type);
 3336150        }
 151
 152        /// <summary>
 153        /// Removes a field.
 154        /// </summary>
 155        /// <param name="fieldName">Name of the field to be removed.</param>
 156        public void RemoveField(string fieldName)
 10157        {
 10158            VerifyFieldNotUsedInProcessings(fieldName);
 2159            FieldDefinitions.Remove(fieldName);
 2160        }
 161
 162        public void AddFieldChangePostProcessing(string fieldName, IFieldValueProcessing fieldValueProcessing)
 2389163        {
 2389164            IFieldDefinition? fieldDefinition = GetField(fieldName);
 2389165            fieldDefinition!.ValuePostChangeProcessings.Add(fieldValueProcessing!);
 2389166        }
 167
 168        public void UpdateFieldChangePostProcessing(string fieldName, string processingName, IFieldValueProcessing field
 1169        {
 1170            IFieldDefinition? fieldDefinition = GetField(fieldName);
 1171            IFieldValueProcessing? fieldValueProcessingToUpdate = fieldDefinition?.ValuePostChangeProcessings
 2172                .FirstOrDefault(valueProcessing => valueProcessing.Name == processingName);
 1173            if (fieldValueProcessingToUpdate != null)
 1174            {
 1175                fieldDefinition!.ValuePostChangeProcessings.Remove(fieldValueProcessingToUpdate);
 1176                fieldDefinition!.ValuePostChangeProcessings.Add(fieldProcessing);
 1177                return;
 178            }
 0179            throw new UnknownEntityException("Field processing", processingName);
 1180        }
 181
 182        public void RemoveFieldChangePostProcessing(string fieldName, string processingName)
 1183        {
 1184            if (FieldDefinitions.TryGetValue(fieldName, out IFieldDefinition? fieldDefinition))
 1185            {
 1186                IFieldValueProcessing? processing = fieldDefinition.ValuePostChangeProcessings
 2187                    .FirstOrDefault(fieldProcessing => fieldProcessing.Name.Equals(processingName));
 1188                if (processing is not null)
 1189                {
 1190                    fieldDefinition.ValuePostChangeProcessings.Remove(processing);
 1191                    return;
 192                }
 0193                throw new UnknownEntityException("Field processing", processingName);
 194            }
 0195            throw new UnknownEntityException(FieldEntityType, fieldName);
 1196        }
 197
 198        private void VerifyFieldNotUsedInProcessings(string fieldName)
 10199        {
 10200            List<String> fieldsUsedInProcessing = [.. FieldDefinitions.Values
 68201                    .Where(field => !field.Name.Equals(fieldName) && field.ValuePostChangeProcessings.Any(valueProcessin
 18202                    .Select(field => field.Name)];
 10203            if (fieldsUsedInProcessing.Count > 0)
 8204            {
 8205                throw new EntityInUseException(FieldEntityType, fieldName, Name, fieldsUsedInProcessing);
 206            }
 2207        }
 208
 209        /// <summary>
 210        /// Gets the C# code for the class.
 211        /// </summary>
 212        /// <returns>C# code of class</returns>
 213        internal string GetCode()
 480214        {
 480215            StringBuilder codeBuilder = new();
 480216            StringBuilder ctorBuilder = new($"public {Name}() {{");
 480217            string baseClass = BaseClass is null ? "Instance" : BaseClass.Name;
 480218            codeBuilder.AppendLine($"public class {Name} : {baseClass} {{");
 480219            FieldDefinitions
 480220                .ForEach((k, v) =>
 2635221                {
 2635222                    codeBuilder.AppendLine(v.GetCode());
 2635223                    ctorBuilder.AppendFormat("Fields.Add(\"{0}\", {0});{0}.Instance = this;", k).AppendLine();
 3115224                });
 480225            ctorBuilder.AppendLine("}");
 480226            return codeBuilder
 480227                .AppendLine(ctorBuilder.ToString())
 480228                .AppendLine("}")
 480229                .ToString();
 480230        }
 231
 232        /// <summary>
 233        /// Clones this instance.
 234        /// </summary>
 235        /// <returns>A new <see cref="Class"/> clone of class instance.</returns>
 236        internal Class Clone()
 152237        {
 152238            var clazz = new Class(Name, BaseClass);
 152239            FieldDefinitions
 988240                .ForEach((k, v) => clazz.FieldDefinitions.Add(k, v.Clone()));
 152241            return clazz;
 152242        }
 243    }
 244}