< 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_18869653307
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        /// <summary>
 14        /// Name of class. Access done through <see cref="Name"/>.
 15        /// </summary>
 64216        private string _name = string.Empty;
 17
 18        /// <summary>Gets or sets the name of the class.</summary>
 19        public string Name
 20        {
 486921            get { return _name; }
 22            set
 64223            {
 64224                IdentifierValidation.ValidateIdentifier("class", value);
 63925                _name = value;
 63926            }
 27        }
 28
 29        /// <summary>
 30        /// Gets or sets the base class.
 31        /// </summary>
 32        /// <value>
 33        /// The base class.
 34        /// </value>
 35        [JsonIgnore]
 129536        public Class? BaseClass { get; set; }
 37
 38        /// <summary>
 39        /// Gets or sets the name of the base class.
 40        /// </summary>
 41        /// <value>
 42        /// The name of the base class.
 43        /// </value>
 81944        public string? BaseClassName { get; set; }
 45
 46        /// <summary>Gets the fields defining the class.</summary>
 1207347        public Dictionary<string, IFieldDefinition> FieldDefinitions { get; set; } = new(StringComparer.OrdinalIgnoreCas
 48
 49        /// <summary>
 50        /// Initializes a new instance of the <see cref="Class"/> class. Used by JSON deserialization.
 51        /// </summary>
 1652        public Class()
 1653        {
 1654        }
 55
 56        /// <summary>
 57        /// Initializes a new instance of the <see cref="Class"/> class.
 58        /// </summary>
 59        /// <param name="className">Name of the class.</param>
 37060        public Class(string className) : this(className, null)
 36761        {
 36762        }
 63
 64        /// <summary>
 65        /// Initializes a new instance of the <see cref="Class"/> class with inheritance from a base class.
 66        /// </summary>
 67        /// <param name="className">Name of the class.</param>
 68        /// <param name="baseClass">Base class.</param>
 62669        public Class(string className, Class? baseClass)
 62670        {
 62671            this.Name = className;
 62372            this.BaseClass = baseClass;
 62373            this.BaseClassName = baseClass?.Name;
 62374        }
 75
 76        /// <summary>
 77        /// Adds a field definition to the class.
 78        /// </summary>
 79        /// <typeparam name="T"></typeparam>
 80        /// <param name="field">The field.</param>
 81        /// <returns>The field once it has been added.</returns>
 82        public IFieldDefinition AddField(IFieldDefinition field)
 266383        {
 266384            return AddField(field, null);
 266285        }
 86
 87        /// <summary>
 88        /// Adds a field with a field formatter.
 89        /// </summary>
 90        /// <typeparam name="T"></typeparam>
 91        /// <param name="field">The <see cref="FieldDefinition{T}"/> to be added.</param>
 92        /// <param name="formatter">The formatter to be used when using ToString()."/>.</param>
 93        /// <returns></returns>
 94        /// <exception cref="pva.SuperV.Engine.Exceptions.EntityAlreadyExistException"></exception>
 95        public IFieldDefinition AddField(IFieldDefinition field, FieldFormatter? formatter)
 298696        {
 298697            if (FieldDefinitions.ContainsKey(field.Name))
 198            {
 199                throw new EntityAlreadyExistException("Field", field.Name);
 100            }
 2985101            field.Formatter = formatter;
 2985102            FieldDefinitions.Add(field.Name, field);
 2985103            return field;
 2985104        }
 105
 106        public IFieldDefinition UpdateField(string fieldName, IFieldDefinition fieldDefinition, FieldFormatter? fieldFor
 4107        {
 4108            if (FieldDefinitions.TryGetValue(fieldName, out IFieldDefinition? fieldToUpdate))
 4109            {
 4110                fieldToUpdate.Update(fieldDefinition, fieldFormatter);
 2111                return fieldToUpdate;
 112            }
 0113            throw new UnknownEntityException("Field", fieldName);
 2114        }
 115
 116        /// <summary>
 117        /// Gets a field.
 118        /// </summary>
 119        /// <param name="fieldName">Name of the field to be retrieved.</param>
 120        /// <returns>The field</returns>
 121        /// <exception cref="pva.SuperV.Engine.Exceptions.UnknownEntityException"></exception>
 122        public IFieldDefinition GetField(string fieldName)
 3646123        {
 3646124            if (FieldDefinitions.TryGetValue(fieldName, out IFieldDefinition? fieldDefinition))
 3645125            {
 3645126                return fieldDefinition;
 127            }
 1128            if (BaseClass is not null)
 0129            {
 0130                return BaseClass.GetField(fieldName);
 131            }
 1132            throw new UnknownEntityException("Field", fieldName);
 3645133        }
 134
 135        /// <summary>
 136        /// Gets a field of a specific type.
 137        /// </summary>
 138        /// <typeparam name="T"></typeparam>
 139        /// <param name="fieldName">Name of the field to be retrieved.</param>
 140        /// <returns>The field</returns>
 141        /// <exception cref="pva.SuperV.Engine.Exceptions.WrongFieldTypeException"></exception>
 142        /// <exception cref="pva.SuperV.Engine.Exceptions.UnknownEntityException"></exception>
 143        public FieldDefinition<T>? GetField<T>(string fieldName)
 1224144        {
 1224145            IFieldDefinition fieldDefinition = GetField(fieldName);
 1223146            if (fieldDefinition.Type == typeof(T))
 1223147            {
 1223148                return fieldDefinition as FieldDefinition<T>;
 149            }
 0150            throw new WrongFieldTypeException(fieldName, typeof(T), fieldDefinition.Type);
 1223151        }
 152
 153        /// <summary>
 154        /// Removes a field.
 155        /// </summary>
 156        /// <param name="fieldName">Name of the field to be removed.</param>
 157        public void RemoveField(string fieldName)
 3158        {
 3159            VerifyFieldNotUsedInProcessings(fieldName);
 2160            FieldDefinitions.Remove(fieldName);
 2161        }
 162
 163        internal void AddFieldChangePostProcessing(string fieldName, IFieldValueProcessing fieldValueProcessing)
 440164        {
 440165            IFieldDefinition? fieldDefinition = GetField(fieldName);
 440166            fieldDefinition!.ValuePostChangeProcessings.Add(fieldValueProcessing!);
 440167        }
 168
 169        internal void UpdateFieldChangePostProcessing(string fieldName, string processingName, IFieldValueProcessing fie
 1170        {
 1171            IFieldDefinition? fieldDefinition = GetField(fieldName);
 1172            IFieldValueProcessing? fieldValueProcessingToUpdate = fieldDefinition?.ValuePostChangeProcessings
 4173                .FirstOrDefault(valueProcessing => valueProcessing.Name == processingName);
 1174            if (fieldValueProcessingToUpdate != null)
 1175            {
 1176                fieldDefinition!.ValuePostChangeProcessings.Remove(fieldValueProcessingToUpdate);
 1177                fieldDefinition!.ValuePostChangeProcessings.Add(fieldProcessing);
 1178                return;
 179            }
 0180            throw new UnknownEntityException("Field processing", processingName);
 1181        }
 182
 183        internal void RemoveFieldChangePostProcessing(string fieldName, string processingName)
 1184        {
 1185            if (FieldDefinitions.TryGetValue(fieldName, out IFieldDefinition? fieldDefinition))
 1186            {
 1187                IFieldValueProcessing? processing = fieldDefinition.ValuePostChangeProcessings
 2188                    .FirstOrDefault(fieldProcessing => fieldProcessing.Name.Equals(processingName));
 1189                if (processing is not null)
 1190                {
 1191                    fieldDefinition.ValuePostChangeProcessings.Remove(processing);
 1192                    return;
 193                }
 0194                throw new UnknownEntityException("Field processing", processingName);
 195            }
 0196            throw new UnknownEntityException("Field", fieldName);
 1197        }
 198
 199        private void VerifyFieldNotUsedInProcessings(string fieldName)
 3200        {
 3201            List<String> fieldsUsedInProcessing = [.. FieldDefinitions.Values
 5202                    .Where(field => !field.Name.Equals(fieldName) && field.ValuePostChangeProcessings.Any(valueProcessin
 4203                    .Select(field => field.Name)];
 3204            if (fieldsUsedInProcessing.Count > 0)
 1205            {
 1206                throw new EntityInUseException("Field", fieldName, Name, fieldsUsedInProcessing);
 207            }
 2208        }
 209
 210        /// <summary>
 211        /// Gets the C# code for the class.
 212        /// </summary>
 213        /// <returns>C# code of class</returns>
 214        internal string GetCode()
 339215        {
 339216            StringBuilder codeBuilder = new();
 339217            StringBuilder ctorBuilder = new($"public {Name}() {{");
 339218            string baseClass = BaseClass is null ? "Instance" : BaseClass.Name;
 339219            codeBuilder.AppendLine($"public class {Name} : {baseClass} {{");
 339220            FieldDefinitions
 339221                .ForEach((k, v) =>
 2192222                {
 2192223                    codeBuilder.AppendLine(v.GetCode());
 2192224                    ctorBuilder.AppendFormat("Fields.Add(\"{0}\", {0});{0}.Instance = this;", k).AppendLine();
 2531225                });
 339226            ctorBuilder.AppendLine("}");
 339227            codeBuilder.AppendLine(ctorBuilder.ToString());
 339228            codeBuilder.AppendLine("}");
 339229            return codeBuilder.ToString();
 339230        }
 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()
 108237        {
 108238            var clazz = new Class(Name, BaseClass);
 108239            FieldDefinitions
 828240                .ForEach((k, v) => clazz.FieldDefinitions.Add(k, v.Clone()));
 108241            return clazz;
 108242        }
 243    }
 244}