/
ValidationResult.cs
173 lines (154 loc) · 8.1 KB
/
ValidationResult.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//
// Swiss QR Bill Generator for .NET
// Copyright (c) 2018 Manuel Bleichenbacher
// Licensed under MIT License
// https://opensource.org/licenses/MIT
//
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Codecrete.SwissQRBill.Generator
{
/// <summary>
/// The validation result, consisting of a list of validation messages
/// and flags indicating the validation state.
/// </summary>
public sealed class ValidationResult
{
private static readonly List<ValidationMessage> EmptyList = new List<ValidationMessage>();
private List<ValidationMessage> _validationMessages;
/// <summary>
/// Gets the list of validation messages.
/// <para>
/// The result is never <c>null</c>.
/// </para>
/// </summary>
/// <value>The validation message list.</value>
public List<ValidationMessage> ValidationMessages => _validationMessages ?? EmptyList;
/// <summary>
/// Gets if this validation result contains any messages.
/// </summary>
/// <value><c>true</c> if the result contains any messages, <c>false</c> otherwise.</value>
public bool HasMessages => _validationMessages != null;
/// <summary>
/// Gets if this validation result contains any warning messages.
/// </summary>
/// <value><c>true</c> if the result contains any warning messages, <c>false</c> otherwise.</value>
public bool HasWarnings
{
get
{
return _validationMessages != null
&& _validationMessages.Any(message => message.Type == ValidationMessage.MessageType.Warning);
}
}
/// <summary>
/// Gets if this validation result contains any error messages.
/// </summary>
/// <value><c>true</c> if the result contains any error messages, <c>false</c> otherwise.</value>
public bool HasErrors
{
get
{
return _validationMessages != null
&& _validationMessages.Any(message => message.Type == ValidationMessage.MessageType.Error);
}
}
/// <summary>
/// Gets if the bill data is valid and the validation therefore has succeeded.
/// <para>
/// A successful validation may still produce warning messages.
/// </para>
/// </summary>
/// <value><c>true</c> if the validation has succeeded, <c>false</c> otherwise.</value>
public bool IsValid => !HasErrors;
/// <summary>
/// Adds a new validation message to this validation result.
/// </summary>
/// <param name="type">The message type.</param>
/// <param name="field">The name of the affected field.</param>
/// <param name="messageKey">The language-neutral message key.</param>
/// <param name="messageParameters">The optional message parameters (text) to be inserted into the localized message.</param>
/// <seealso cref="ValidationMessage"/>
public void AddMessage(ValidationMessage.MessageType type, string field, string messageKey, string[] messageParameters = null)
{
var message = new ValidationMessage(type, field, messageKey, messageParameters);
if (_validationMessages == null)
{
_validationMessages = new List<ValidationMessage>();
}
_validationMessages.Add(message);
}
/// <summary>
/// Gets or sets the cleaned bill data.
/// <para>
/// As part of the validation, the bill data is cleaned, i.e. leading and trailing whitespace is trimmed,
/// empty values are replaced with <c>null</c>, invalid characters are replaced and too long data is truncated.
/// The result is the cleaned bill data.
/// </para>
/// </summary>
/// <value>The cleaned bill data.</value>
public Bill CleanedBill { get; set; }
/// <summary>
/// Gets a human-readable description of the validation problems.
/// <para>
/// The description includes errors only.
/// </para>
/// </summary>
/// <value>The description.</value>
public string Description
{
get
{
if (!HasErrors)
{
return "Valid bill data";
}
var sb = new StringBuilder();
foreach (var message in ValidationMessages.Where(message => message.Type == ValidationMessage.MessageType.Error))
{
if (sb.Length > 0)
sb.Append("; ");
var desc = ErrorMessages.ContainsKey(message.MessageKey) ? ErrorMessages[message.MessageKey] : "Unknown error";
switch (message.MessageKey)
{
case ValidationConstants.KeyFieldValueMissing:
case ValidationConstants.KeyReplacedUnsupportedCharacters:
desc = string.Format(desc, message.Field);
break;
case ValidationConstants.KeyFieldValueTooLong:
case ValidationConstants.KeyFieldValueClipped:
desc = string.Format(desc, message.Field, message.MessageParameters[0]);
break;
}
sb.Append(desc);
sb.Append(" (");
sb.Append(message.MessageKey);
sb.Append(")");
}
return sb.ToString();
}
}
private static readonly Dictionary<string, string> ErrorMessages = new Dictionary<string, string>
{
{ ValidationConstants.KeyCurrencyNotChfOrEur, "currency should be \"CHF\" or \"EUR\"" },
{ ValidationConstants.KeyAmountOutsideValidRange, "amount should be between 0.01 and 999 999 999.99" },
{ ValidationConstants.KeyAccountIbanNotFromChOrLi, "account number should start with \"CH\" or \"LI\"" },
{ ValidationConstants.KeyAccountIbanInvalid, "account number is not a valid IBAN (invalid format or checksum)" },
{ ValidationConstants.KeyRefInvalid, "reference is invalid; it is neither a valid QR reference nor a valid ISO 11649 reference" },
{ ValidationConstants.KeyQrRefMissing, "QR reference is missing; it is mandatory for payments to a QR-IBAN account" },
{ ValidationConstants.KeyCredRefInvalidUseForQrIban, "for payments to a QR-IBAN account, a QR reference is required (an ISO 11649 reference may not be used)" },
{ ValidationConstants.KeyQrRefInvalidUseForNonQrIban, "a QR reference is only allowed for payments to a QR-IBAN account" },
{ ValidationConstants.KeyRefTypeInvalid, "reference type should be one of \"QRR\", \"SCOR\" and \"NON\" and match the reference" },
{ ValidationConstants.KeyFieldValueMissing, "field \"{0}\" may not be empty" },
{ ValidationConstants.KeyAddressTypeConflict, "fields for either structured address or combined elements address may be filled but not both" },
{ ValidationConstants.KeyCountryCodeInvalid, "country code is invalid; it should consist of two letters" },
{ ValidationConstants.KeyFieldValueClipped, "the value for field \"{0}\" has been clipped to not exceed the maximum length of {1} characters" },
{ ValidationConstants.KeyFieldValueTooLong, "the value for field \"{0}\" should not exceed a length of {1} characters" },
{ ValidationConstants.KeyAdditionalInfoTooLong, "the additional information and the structured bill information combined should not exceed 140 characters" },
{ ValidationConstants.KeyReplacedUnsupportedCharacters, "unsupported characters have been replaced in field \"{0}\"" },
{ ValidationConstants.KeyAltSchemeMaxExceeded, "no more than two alternative schemes may be used" },
{ ValidationConstants.KeyBillInfoInvalid, "structured bill information must start with \"//\"" }
};
}
}