| | | 1 | | using pva.SuperV.Engine.Exceptions; |
| | | 2 | | using pva.SuperV.Engine.HistoryStorage; |
| | | 3 | | |
| | | 4 | | namespace pva.SuperV.Engine.Processing |
| | | 5 | | { |
| | | 6 | | /// <summary> |
| | | 7 | | /// Field value historization processing. |
| | | 8 | | /// </summary> |
| | | 9 | | /// <typeparam name="T"></typeparam> |
| | | 10 | | public class HistorizationProcessing<T> : FieldValueProcessing<T>, IHistorizationProcessing |
| | | 11 | | { |
| | | 12 | | /// <summary> |
| | | 13 | | /// Associated history repository. |
| | | 14 | | /// </summary> |
| | 575 | 15 | | public HistoryRepository? HistoryRepository { get; set; } |
| | | 16 | | |
| | | 17 | | /// <summary> |
| | | 18 | | /// Field providing the timestamp of time serie. |
| | | 19 | | /// </summary> |
| | 39 | 20 | | public FieldDefinition<DateTime>? TimestampFieldDefinition { get; set; } |
| | | 21 | | |
| | | 22 | | /// <summary> |
| | | 23 | | /// List of fields whose value is to be historized. |
| | | 24 | | /// </summary> |
| | 2273 | 25 | | public List<IFieldDefinition> FieldsToHistorize { get; } = []; |
| | | 26 | | |
| | | 27 | | /// <summary> |
| | | 28 | | /// The class time serie ID returned from history storage. |
| | | 29 | | /// </summary> |
| | 489 | 30 | | public string? ClassTimeSerieId { get; set; } |
| | | 31 | | |
| | | 32 | | /// <summary> |
| | | 33 | | /// Initializes a new instance of the <see cref="HistorizationProcessing{T}"/> class. Used for deserialization. |
| | | 34 | | /// </summary> |
| | 2 | 35 | | public HistorizationProcessing() |
| | 2 | 36 | | { |
| | 2 | 37 | | } |
| | | 38 | | |
| | | 39 | | /// <summary> |
| | | 40 | | /// Initializes a new instance. |
| | | 41 | | /// </summary> |
| | | 42 | | /// <param name="name">Name of instance.</param> |
| | | 43 | | /// <param name="project">Project.</param> |
| | | 44 | | /// <param name="clazz">Class.</param> |
| | | 45 | | /// <param name="trigerringFieldName">Field trigerring the processing.</param> |
| | | 46 | | /// <param name="historyRepositoryName">Name of history repository (<see cref="HistoryRepository"/>).</param> |
| | | 47 | | /// <param name="timestampFieldName">Name of the timestamp field. If null, the timestamp of tirgerring field zil |
| | | 48 | | /// <param name="fieldsToHistorize">List of fields to historize.</param> |
| | | 49 | | public HistorizationProcessing(string name, Project project, Class clazz, string trigerringFieldName, |
| | | 50 | | string historyRepositoryName, string? timestampFieldName, List<string> fieldsToHistorize) |
| | 296 | 51 | | : base(name) |
| | 296 | 52 | | { |
| | 296 | 53 | | CtorArguments.Add(trigerringFieldName); |
| | 296 | 54 | | CtorArguments.Add(historyRepositoryName); |
| | 296 | 55 | | CtorArguments.Add(timestampFieldName ?? ""); |
| | 296 | 56 | | fieldsToHistorize.ForEach(fieldtoHistorize => |
| | 2191 | 57 | | CtorArguments.Add(fieldtoHistorize)); |
| | 296 | 58 | | ValidateParameters(project, clazz, trigerringFieldName, historyRepositoryName, timestampFieldName, fieldsToH |
| | 296 | 59 | | } |
| | | 60 | | |
| | | 61 | | /// <summary> |
| | | 62 | | /// Validate the processing parameters. |
| | | 63 | | /// </summary> |
| | | 64 | | /// <param name="project">Project.</param> |
| | | 65 | | /// <param name="clazz">Class.</param> |
| | | 66 | | /// <param name="trigerringFieldName">Field trigerring the processing.</param> |
| | | 67 | | /// <param name="historyRepositoryName">Name of history repository (<see cref="HistoryRepository"/>).</param> |
| | | 68 | | /// <param name="timestampFieldName">Name of the timestamp field. If null, the timestamp of tirgerring field zil |
| | | 69 | | /// <param name="fieldsToHistorize">List of fields to historize.</param> |
| | | 70 | | /// <exception cref="UnknownEntityException"></exception> |
| | | 71 | | private void ValidateParameters(Project project, Class clazz, string trigerringFieldName, string historyReposito |
| | 298 | 72 | | { |
| | 298 | 73 | | TrigerringFieldDefinition = GetFieldDefinition<T>(clazz, trigerringFieldName); |
| | 298 | 74 | | if (!string.IsNullOrEmpty(timestampFieldName)) |
| | 0 | 75 | | { |
| | 0 | 76 | | TimestampFieldDefinition = GetFieldDefinition<DateTime>(clazz, timestampFieldName); |
| | 0 | 77 | | } |
| | 298 | 78 | | if (project.HistoryRepositories.TryGetValue(historyRepositoryName, out var repository)) |
| | 298 | 79 | | { |
| | 298 | 80 | | HistoryRepository = repository; |
| | 298 | 81 | | } |
| | | 82 | | else |
| | 0 | 83 | | { |
| | 0 | 84 | | throw new UnknownEntityException("History repository", historyRepositoryName); |
| | | 85 | | } |
| | 298 | 86 | | fieldsToHistorize.ForEach(fieldToHistorize => |
| | 1908 | 87 | | { |
| | 1908 | 88 | | IFieldDefinition? fieldDefinition = GetFieldDefinition(clazz, fieldToHistorize); |
| | 1908 | 89 | | if (fieldDefinition is not null) |
| | 1908 | 90 | | { |
| | 1908 | 91 | | FieldsToHistorize.Add(fieldDefinition); |
| | 1908 | 92 | | } |
| | 2206 | 93 | | }); |
| | 298 | 94 | | } |
| | | 95 | | |
| | | 96 | | /// <summary> |
| | | 97 | | /// Build the processing after deserialization. |
| | | 98 | | /// </summary> |
| | | 99 | | /// <param name="project">Project.</param> |
| | | 100 | | /// <param name="clazz">Class.</param> |
| | | 101 | | public override void BuildAfterDeserialization(Project project, Class clazz) |
| | 2 | 102 | | { |
| | 2 | 103 | | string trigerringFieldName = GetCtorArgument<string>(0)!; |
| | 2 | 104 | | string historyRepositoryName = GetCtorArgument<string>(1)!; |
| | 2 | 105 | | string? timestampFieldName = GetCtorArgument<string?>(2); |
| | 2 | 106 | | List<string> fieldsToHistorize = []; |
| | 30 | 107 | | for (int index = 3; index < CtorArguments.Count - 1; index++) |
| | 13 | 108 | | { |
| | 13 | 109 | | fieldsToHistorize.Add(GetCtorArgument<string>(index)!); |
| | 13 | 110 | | } |
| | 2 | 111 | | ClassTimeSerieId = GetCtorArgument<string?>(CtorArguments.Count - 1); |
| | 2 | 112 | | ValidateParameters(project, clazz, trigerringFieldName, historyRepositoryName, timestampFieldName, fieldsToH |
| | 2 | 113 | | } |
| | | 114 | | |
| | | 115 | | public bool IsUsingRepository(string historyRepositoryName) |
| | 1 | 116 | | => HistoryRepository is not null && HistoryRepository.Name.Equals(historyRepositoryName); |
| | | 117 | | |
| | | 118 | | public override bool IsFieldUsed(string fieldName) |
| | 1 | 119 | | => (TimestampFieldDefinition is not null && TimestampFieldDefinition.Name.Equals(fieldName)) |
| | 3 | 120 | | || FieldsToHistorize.Any(field => field.Name.Equals(fieldName)); |
| | | 121 | | |
| | | 122 | | /// <summary> |
| | | 123 | | /// Upserts the time series in history storage. |
| | | 124 | | /// </summary> |
| | | 125 | | /// <param name="projectName">Name of project.</param> |
| | | 126 | | /// <param name="className">Name of class.</param> |
| | | 127 | | public void UpsertInHistoryStorage(string projectName, string className) |
| | 220 | 128 | | { |
| | 220 | 129 | | ClassTimeSerieId = HistoryRepository?.UpsertClassTimeSerie(projectName, className, this); |
| | 219 | 130 | | CtorArguments.Add(ClassTimeSerieId!); |
| | 219 | 131 | | } |
| | | 132 | | |
| | | 133 | | /// <summary> |
| | | 134 | | /// Processes the trigerring field value change. |
| | | 135 | | /// </summary> |
| | | 136 | | /// <param name="instance">Instance whose field has changed.</param> |
| | | 137 | | /// <param name="changedField">Changed field.</param> |
| | | 138 | | /// <param name="valueChanged">Indicates if the value changed or not.</param> |
| | | 139 | | /// <param name="previousValue">Previous value 9i.e. before change).</param> |
| | | 140 | | /// <param name="currentValue">New value.</param> |
| | | 141 | | public override void ProcessValue(IInstance instance, Field<T> changedField, bool valueChanged, T previousValue, |
| | 26 | 142 | | { |
| | | 143 | | DateTime? historyTs; |
| | 26 | 144 | | if (TimestampFieldDefinition != null) |
| | 0 | 145 | | { |
| | 0 | 146 | | Field<DateTime>? timestamp = GetInstanceField<DateTime>(instance, TimestampFieldDefinition?.Name); |
| | 0 | 147 | | historyTs = timestamp?.Value; |
| | 0 | 148 | | } |
| | | 149 | | else |
| | 26 | 150 | | { |
| | 26 | 151 | | historyTs = changedField.Timestamp.GetValueOrDefault(); |
| | 26 | 152 | | } |
| | 26 | 153 | | List<IField> fieldsToHistorize = []; |
| | 26 | 154 | | FieldsToHistorize.ForEach(fieldToHistorize => |
| | 118 | 155 | | { |
| | 118 | 156 | | IField? field = GetInstanceField(instance, fieldToHistorize.Name); |
| | 118 | 157 | | if (field != null) |
| | 118 | 158 | | { |
| | 118 | 159 | | fieldsToHistorize.Add(field); |
| | 118 | 160 | | } |
| | 144 | 161 | | }); |
| | 26 | 162 | | HistoryRepository?.HistorizeValues(ClassTimeSerieId!, instance, historyTs ?? DateTime.Now, changedField.Qual |
| | 26 | 163 | | } |
| | | 164 | | } |
| | | 165 | | } |