@itwin/core-quantity 3.0.0-dev.76 → 3.0.0-dev.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/{Constants.d.ts → cjs/Constants.d.ts} +0 -0
- package/lib/cjs/Constants.d.ts.map +1 -0
- package/lib/{Constants.js → cjs/Constants.js} +0 -0
- package/lib/cjs/Constants.js.map +1 -0
- package/lib/{Exception.d.ts → cjs/Exception.d.ts} +0 -0
- package/lib/cjs/Exception.d.ts.map +1 -0
- package/lib/{Exception.js → cjs/Exception.js} +0 -0
- package/lib/cjs/Exception.js.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/Format.d.ts +0 -0
- package/lib/cjs/Formatter/Format.d.ts.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/Format.js +0 -0
- package/lib/cjs/Formatter/Format.js.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/FormatEnums.d.ts +0 -0
- package/lib/cjs/Formatter/FormatEnums.d.ts.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/FormatEnums.js +0 -0
- package/lib/cjs/Formatter/FormatEnums.js.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/Formatter.d.ts +0 -0
- package/lib/cjs/Formatter/Formatter.d.ts.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/Formatter.js +0 -0
- package/lib/cjs/Formatter/Formatter.js.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/FormatterSpec.d.ts +0 -0
- package/lib/cjs/Formatter/FormatterSpec.d.ts.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/FormatterSpec.js +0 -0
- package/lib/cjs/Formatter/FormatterSpec.js.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/Interfaces.d.ts +0 -0
- package/lib/cjs/Formatter/Interfaces.d.ts.map +1 -0
- package/lib/{Formatter → cjs/Formatter}/Interfaces.js +0 -0
- package/lib/cjs/Formatter/Interfaces.js.map +1 -0
- package/lib/{Interfaces.d.ts → cjs/Interfaces.d.ts} +0 -0
- package/lib/cjs/Interfaces.d.ts.map +1 -0
- package/lib/{Interfaces.js → cjs/Interfaces.js} +0 -0
- package/lib/cjs/Interfaces.js.map +1 -0
- package/lib/{Parser.d.ts → cjs/Parser.d.ts} +0 -0
- package/lib/cjs/Parser.d.ts.map +1 -0
- package/lib/{Parser.js → cjs/Parser.js} +0 -0
- package/lib/cjs/Parser.js.map +1 -0
- package/lib/{ParserSpec.d.ts → cjs/ParserSpec.d.ts} +0 -0
- package/lib/cjs/ParserSpec.d.ts.map +1 -0
- package/lib/{ParserSpec.js → cjs/ParserSpec.js} +0 -0
- package/lib/cjs/ParserSpec.js.map +1 -0
- package/lib/{Quantity.d.ts → cjs/Quantity.d.ts} +0 -0
- package/lib/cjs/Quantity.d.ts.map +1 -0
- package/lib/{Quantity.js → cjs/Quantity.js} +0 -0
- package/lib/cjs/Quantity.js.map +1 -0
- package/lib/{Unit.d.ts → cjs/Unit.d.ts} +0 -0
- package/lib/cjs/Unit.d.ts.map +1 -0
- package/lib/{Unit.js → cjs/Unit.js} +0 -0
- package/lib/cjs/Unit.js.map +1 -0
- package/lib/{core-quantity.d.ts → cjs/core-quantity.d.ts} +0 -0
- package/lib/cjs/core-quantity.d.ts.map +1 -0
- package/lib/{core-quantity.js → cjs/core-quantity.js} +0 -0
- package/lib/cjs/core-quantity.js.map +1 -0
- package/lib/esm/Constants.d.ts +28 -0
- package/lib/esm/Constants.d.ts.map +1 -0
- package/lib/esm/Constants.js +49 -0
- package/lib/esm/Constants.js.map +1 -0
- package/lib/esm/Exception.d.ts +27 -0
- package/lib/esm/Exception.d.ts.map +1 -0
- package/lib/esm/Exception.js +34 -0
- package/lib/esm/Exception.js.map +1 -0
- package/lib/esm/Formatter/Format.d.ts +96 -0
- package/lib/esm/Formatter/Format.d.ts.map +1 -0
- package/lib/esm/Formatter/Format.js +550 -0
- package/lib/esm/Formatter/Format.js.map +1 -0
- package/lib/esm/Formatter/FormatEnums.d.ts +89 -0
- package/lib/esm/Formatter/FormatEnums.d.ts.map +1 -0
- package/lib/esm/Formatter/FormatEnums.js +99 -0
- package/lib/esm/Formatter/FormatEnums.js.map +1 -0
- package/lib/esm/Formatter/Formatter.d.ts +45 -0
- package/lib/esm/Formatter/Formatter.d.ts.map +1 -0
- package/lib/esm/Formatter/Formatter.js +368 -0
- package/lib/esm/Formatter/Formatter.js.map +1 -0
- package/lib/esm/Formatter/FormatterSpec.d.ts +40 -0
- package/lib/esm/Formatter/FormatterSpec.d.ts.map +1 -0
- package/lib/esm/Formatter/FormatterSpec.js +98 -0
- package/lib/esm/Formatter/FormatterSpec.js.map +1 -0
- package/lib/esm/Formatter/Interfaces.d.ts +63 -0
- package/lib/esm/Formatter/Interfaces.d.ts.map +1 -0
- package/lib/esm/Formatter/Interfaces.js +14 -0
- package/lib/esm/Formatter/Interfaces.js.map +1 -0
- package/lib/esm/Interfaces.d.ts +75 -0
- package/lib/esm/Interfaces.d.ts.map +1 -0
- package/lib/esm/Interfaces.js +9 -0
- package/lib/esm/Interfaces.js.map +1 -0
- package/lib/esm/Parser.d.ts +94 -0
- package/lib/esm/Parser.d.ts.map +1 -0
- package/lib/esm/Parser.js +584 -0
- package/lib/esm/Parser.js.map +1 -0
- package/lib/esm/ParserSpec.d.ts +35 -0
- package/lib/esm/ParserSpec.d.ts.map +1 -0
- package/lib/esm/ParserSpec.js +44 -0
- package/lib/esm/ParserSpec.js.map +1 -0
- package/lib/esm/Quantity.d.ts +28 -0
- package/lib/esm/Quantity.d.ts.map +1 -0
- package/lib/esm/Quantity.js +43 -0
- package/lib/esm/Quantity.js.map +1 -0
- package/lib/esm/Unit.d.ts +27 -0
- package/lib/esm/Unit.d.ts.map +1 -0
- package/lib/esm/Unit.js +41 -0
- package/lib/esm/Unit.js.map +1 -0
- package/lib/esm/core-quantity.d.ts +20 -0
- package/lib/esm/core-quantity.d.ts.map +1 -0
- package/lib/esm/core-quantity.js +24 -0
- package/lib/esm/core-quantity.js.map +1 -0
- package/package.json +11 -8
- package/lib/Constants.d.ts.map +0 -1
- package/lib/Constants.js.map +0 -1
- package/lib/Exception.d.ts.map +0 -1
- package/lib/Exception.js.map +0 -1
- package/lib/Formatter/Format.d.ts.map +0 -1
- package/lib/Formatter/Format.js.map +0 -1
- package/lib/Formatter/FormatEnums.d.ts.map +0 -1
- package/lib/Formatter/FormatEnums.js.map +0 -1
- package/lib/Formatter/Formatter.d.ts.map +0 -1
- package/lib/Formatter/Formatter.js.map +0 -1
- package/lib/Formatter/FormatterSpec.d.ts.map +0 -1
- package/lib/Formatter/FormatterSpec.js.map +0 -1
- package/lib/Formatter/Interfaces.d.ts.map +0 -1
- package/lib/Formatter/Interfaces.js.map +0 -1
- package/lib/Interfaces.d.ts.map +0 -1
- package/lib/Interfaces.js.map +0 -1
- package/lib/Parser.d.ts.map +0 -1
- package/lib/Parser.js.map +0 -1
- package/lib/ParserSpec.d.ts.map +0 -1
- package/lib/ParserSpec.js.map +0 -1
- package/lib/Quantity.d.ts.map +0 -1
- package/lib/Quantity.js.map +0 -1
- package/lib/Unit.d.ts.map +0 -1
- package/lib/Unit.js.map +0 -1
- package/lib/core-quantity.d.ts.map +0 -1
- package/lib/core-quantity.js.map +0 -1
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
/** @packageDocumentation
|
|
6
|
+
* @module Quantity
|
|
7
|
+
*/
|
|
8
|
+
import { QuantityConstants } from "../Constants";
|
|
9
|
+
import { QuantityError, QuantityStatus } from "../Exception";
|
|
10
|
+
import { DecimalPrecision, FormatTraits, FormatType, FractionalPrecision, ScientificType, ShowSignOption } from "./FormatEnums";
|
|
11
|
+
import { isCustomFormatProps } from "./Interfaces";
|
|
12
|
+
// cSpell:ignore ZERONORMALIZED, nosign, onlynegative, signalways, negativeparentheses
|
|
13
|
+
// cSpell:ignore trailzeroes, keepsinglezero, zeroempty, keepdecimalpoint, applyrounding, fractiondash, showunitlabel, prependunitlabel, exponentonlynegative
|
|
14
|
+
/** A class used to define the specifications for formatting quantity values. This class is typically loaded by reading [[FormatProps]].
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
export class Format {
|
|
18
|
+
/** Constructor
|
|
19
|
+
* @param name The name of a format specification. TODO: make optional or remove
|
|
20
|
+
*/
|
|
21
|
+
constructor(name) {
|
|
22
|
+
this._name = "";
|
|
23
|
+
this._roundFactor = 0.0;
|
|
24
|
+
this._type = FormatType.Decimal; // required; options are decimal, fractional, scientific, station
|
|
25
|
+
this._precision = DecimalPrecision.Six; // required
|
|
26
|
+
this._showSignOption = ShowSignOption.OnlyNegative; // options: noSign, onlyNegative, signAlways, negativeParentheses
|
|
27
|
+
this._decimalSeparator = QuantityConstants.LocaleSpecificDecimalSeparator;
|
|
28
|
+
this._thousandSeparator = QuantityConstants.LocaleSpecificThousandSeparator;
|
|
29
|
+
this._uomSeparator = " "; // optional; default is " "; defined separator between magnitude and the unit
|
|
30
|
+
this._stationSeparator = "+"; // optional; default is "+"
|
|
31
|
+
this._formatTraits = 0x0;
|
|
32
|
+
this._spacer = " "; // optional; default is " "
|
|
33
|
+
this._includeZero = true; // optional; default is true
|
|
34
|
+
this._name = name;
|
|
35
|
+
}
|
|
36
|
+
get name() { return this._name; }
|
|
37
|
+
get roundFactor() { return this._roundFactor; }
|
|
38
|
+
get type() { return this._type; }
|
|
39
|
+
get precision() { return this._precision; }
|
|
40
|
+
get minWidth() { return this._minWidth; }
|
|
41
|
+
get scientificType() { return this._scientificType; }
|
|
42
|
+
get showSignOption() { return this._showSignOption; }
|
|
43
|
+
get decimalSeparator() { return this._decimalSeparator; }
|
|
44
|
+
get thousandSeparator() { return this._thousandSeparator; }
|
|
45
|
+
get uomSeparator() { return this._uomSeparator; }
|
|
46
|
+
get stationSeparator() { return this._stationSeparator; }
|
|
47
|
+
get stationOffsetSize() { return this._stationOffsetSize; }
|
|
48
|
+
get formatTraits() { return this._formatTraits; }
|
|
49
|
+
get spacer() { return this._spacer; }
|
|
50
|
+
get includeZero() { return this._includeZero; }
|
|
51
|
+
get units() { return this._units; }
|
|
52
|
+
get hasUnits() { return this._units !== undefined && this._units.length > 0; }
|
|
53
|
+
get customProps() { return this._customProps; }
|
|
54
|
+
// parse and toString methods
|
|
55
|
+
static scientificTypeToString(scientificType) {
|
|
56
|
+
if (scientificType === ScientificType.Normalized)
|
|
57
|
+
return "Normalized";
|
|
58
|
+
else
|
|
59
|
+
return "ZeroNormalized";
|
|
60
|
+
}
|
|
61
|
+
/** This method parses input string that is typically extracted for persisted JSON data and validates that the string is a valid ScientificType. Throws exception if not valid. */
|
|
62
|
+
static parseScientificType(scientificType, formatName) {
|
|
63
|
+
switch (scientificType.toLowerCase()) {
|
|
64
|
+
case "normalized":
|
|
65
|
+
return ScientificType.Normalized;
|
|
66
|
+
case "zeronormalized":
|
|
67
|
+
return ScientificType.ZeroNormalized;
|
|
68
|
+
default:
|
|
69
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'SCIENTIFIC_TYPE' attribute.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Method used when generating a JSON object that represents this Format. */
|
|
73
|
+
static showSignOptionToString(showSign) {
|
|
74
|
+
switch (showSign) {
|
|
75
|
+
case ShowSignOption.NegativeParentheses:
|
|
76
|
+
return "NegativeParentheses";
|
|
77
|
+
case ShowSignOption.NoSign:
|
|
78
|
+
return "NoSign";
|
|
79
|
+
case ShowSignOption.OnlyNegative:
|
|
80
|
+
return "OnlyNegative";
|
|
81
|
+
case ShowSignOption.SignAlways:
|
|
82
|
+
return "SignAlways";
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** This method parses input string that is typically extracted for persisted JSON data and validates that the string is a valid ShowSignOption. Throws exception if not valid. */
|
|
86
|
+
static parseShowSignOption(showSignOption, formatName) {
|
|
87
|
+
switch (showSignOption.toLowerCase()) {
|
|
88
|
+
case "nosign":
|
|
89
|
+
return ShowSignOption.NoSign;
|
|
90
|
+
case "onlynegative":
|
|
91
|
+
return ShowSignOption.OnlyNegative;
|
|
92
|
+
case "signalways":
|
|
93
|
+
return ShowSignOption.SignAlways;
|
|
94
|
+
case "negativeparentheses":
|
|
95
|
+
return ShowSignOption.NegativeParentheses;
|
|
96
|
+
default:
|
|
97
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'showSignOption' attribute.`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
static isFormatTraitSetInProps(formatProps, trait) {
|
|
101
|
+
if (!formatProps.formatTraits)
|
|
102
|
+
return false;
|
|
103
|
+
const formatTraits = Array.isArray(formatProps.formatTraits) ? formatProps.formatTraits : formatProps.formatTraits.split(/,|;|\|/);
|
|
104
|
+
const traitStr = Format.getTraitString(trait);
|
|
105
|
+
return formatTraits.find((traitEntry) => traitStr === traitEntry) ? true : false;
|
|
106
|
+
}
|
|
107
|
+
/** Get string used in FormatProps */
|
|
108
|
+
static getTraitString(trait) {
|
|
109
|
+
switch (trait) {
|
|
110
|
+
case FormatTraits.TrailZeroes:
|
|
111
|
+
return "trailZeroes";
|
|
112
|
+
case FormatTraits.KeepSingleZero:
|
|
113
|
+
return "keepSingleZero";
|
|
114
|
+
case FormatTraits.ZeroEmpty:
|
|
115
|
+
return "zeroEmpty";
|
|
116
|
+
case FormatTraits.KeepDecimalPoint:
|
|
117
|
+
return "keepDecimalPoint";
|
|
118
|
+
case FormatTraits.ApplyRounding:
|
|
119
|
+
return "applyRounding";
|
|
120
|
+
case FormatTraits.FractionDash:
|
|
121
|
+
return "fractionDash";
|
|
122
|
+
case FormatTraits.ShowUnitLabel:
|
|
123
|
+
return "showUnitLabel";
|
|
124
|
+
case FormatTraits.PrependUnitLabel:
|
|
125
|
+
return "prependUnitLabel";
|
|
126
|
+
case FormatTraits.Use1000Separator:
|
|
127
|
+
return "use1000Separator";
|
|
128
|
+
case FormatTraits.ExponentOnlyNegative:
|
|
129
|
+
default:
|
|
130
|
+
return "exponentOnlyNegative";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Method used when generating a JSON object that represents this Format. */
|
|
134
|
+
static formatTraitsToArray(currentFormatTrait) {
|
|
135
|
+
const formatTraitsArr = Array();
|
|
136
|
+
if ((currentFormatTrait & FormatTraits.TrailZeroes) === FormatTraits.TrailZeroes)
|
|
137
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.TrailZeroes));
|
|
138
|
+
if ((currentFormatTrait & FormatTraits.KeepSingleZero) === FormatTraits.KeepSingleZero)
|
|
139
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.KeepSingleZero));
|
|
140
|
+
if ((currentFormatTrait & FormatTraits.ZeroEmpty) === FormatTraits.ZeroEmpty)
|
|
141
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.ZeroEmpty));
|
|
142
|
+
if ((currentFormatTrait & FormatTraits.KeepDecimalPoint) === FormatTraits.KeepDecimalPoint)
|
|
143
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.KeepDecimalPoint));
|
|
144
|
+
if ((currentFormatTrait & FormatTraits.ApplyRounding) === FormatTraits.ApplyRounding)
|
|
145
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.ApplyRounding));
|
|
146
|
+
if ((currentFormatTrait & FormatTraits.FractionDash) === FormatTraits.FractionDash)
|
|
147
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.FractionDash));
|
|
148
|
+
if ((currentFormatTrait & FormatTraits.ShowUnitLabel) === FormatTraits.ShowUnitLabel)
|
|
149
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.ShowUnitLabel));
|
|
150
|
+
if ((currentFormatTrait & FormatTraits.PrependUnitLabel) === FormatTraits.PrependUnitLabel)
|
|
151
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.PrependUnitLabel));
|
|
152
|
+
if ((currentFormatTrait & FormatTraits.Use1000Separator) === FormatTraits.Use1000Separator)
|
|
153
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.Use1000Separator));
|
|
154
|
+
// NOTE: the formatter does not current use trait ExponentOnlyNegative
|
|
155
|
+
if ((currentFormatTrait & FormatTraits.ExponentOnlyNegative) === FormatTraits.ExponentOnlyNegative)
|
|
156
|
+
formatTraitsArr.push(Format.getTraitString(FormatTraits.ExponentOnlyNegative));
|
|
157
|
+
return formatTraitsArr;
|
|
158
|
+
}
|
|
159
|
+
/** This method parses input string that is typically extracted for persisted JSON data and validates that the string is a valid FormatTrait. Throws exception if not valid. */
|
|
160
|
+
static parseFormatTrait(stringToCheck, currentFormatTrait) {
|
|
161
|
+
switch (stringToCheck.toLowerCase()) {
|
|
162
|
+
case "trailzeroes":
|
|
163
|
+
return currentFormatTrait | FormatTraits.TrailZeroes;
|
|
164
|
+
case "keepsinglezero":
|
|
165
|
+
return currentFormatTrait | FormatTraits.KeepSingleZero; // keep single when format type is Decimal
|
|
166
|
+
case "zeroempty":
|
|
167
|
+
return currentFormatTrait | FormatTraits.ZeroEmpty;
|
|
168
|
+
case "keepdecimalpoint":
|
|
169
|
+
return currentFormatTrait | FormatTraits.KeepDecimalPoint; // add decimal point when no fractional part and format type is Decimal
|
|
170
|
+
case "applyrounding":
|
|
171
|
+
return currentFormatTrait | FormatTraits.ApplyRounding;
|
|
172
|
+
case "fractiondash":
|
|
173
|
+
return currentFormatTrait | FormatTraits.FractionDash;
|
|
174
|
+
case "showunitlabel":
|
|
175
|
+
return currentFormatTrait | FormatTraits.ShowUnitLabel;
|
|
176
|
+
case "prependunitlabel":
|
|
177
|
+
return currentFormatTrait | FormatTraits.PrependUnitLabel;
|
|
178
|
+
case "use1000separator":
|
|
179
|
+
return currentFormatTrait | FormatTraits.Use1000Separator;
|
|
180
|
+
case "exponentonlynegative":
|
|
181
|
+
return currentFormatTrait | FormatTraits.ExponentOnlyNegative;
|
|
182
|
+
default:
|
|
183
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `Format has an invalid 'formatTraits' option.`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/** Get FormatTrait from entry in FormatProps */
|
|
187
|
+
static parseFormatTraits(formatTraitsFromJson) {
|
|
188
|
+
if (!formatTraitsFromJson)
|
|
189
|
+
return undefined;
|
|
190
|
+
const formatTraits = Array.isArray(formatTraitsFromJson) ? formatTraitsFromJson : formatTraitsFromJson.split(/,|;|\|/);
|
|
191
|
+
let traits = 0;
|
|
192
|
+
for (const traitStr of formatTraits) {
|
|
193
|
+
traits = Format.parseFormatTrait(traitStr, traits);
|
|
194
|
+
}
|
|
195
|
+
if (0 === traits)
|
|
196
|
+
return undefined;
|
|
197
|
+
return traits;
|
|
198
|
+
}
|
|
199
|
+
/** Method used when generating a JSON object that represents this Format. */
|
|
200
|
+
static formatTypeToString(type) {
|
|
201
|
+
switch (type) {
|
|
202
|
+
case FormatType.Decimal:
|
|
203
|
+
return "Decimal";
|
|
204
|
+
case FormatType.Scientific:
|
|
205
|
+
return "Scientific";
|
|
206
|
+
case FormatType.Station:
|
|
207
|
+
return "Station";
|
|
208
|
+
case FormatType.Fractional:
|
|
209
|
+
return "Fractional";
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/** This method parses input string that is typically extracted for persisted JSON data and validates that the string is a valid FormatType. Throws exception if not valid. */
|
|
213
|
+
static parseFormatType(jsonObjType, formatName) {
|
|
214
|
+
switch (jsonObjType.toLowerCase()) {
|
|
215
|
+
case "decimal":
|
|
216
|
+
return FormatType.Decimal;
|
|
217
|
+
case "scientific":
|
|
218
|
+
return FormatType.Scientific;
|
|
219
|
+
case "station":
|
|
220
|
+
return FormatType.Station;
|
|
221
|
+
case "fractional":
|
|
222
|
+
return FormatType.Fractional;
|
|
223
|
+
default:
|
|
224
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'type' attribute.`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/** This method validates the input value, that is typically extracted for persisted JSON data, is a valid DecimalPrecision. Throws exception if not valid. */
|
|
228
|
+
static parseDecimalPrecision(jsonObjPrecision) {
|
|
229
|
+
switch (jsonObjPrecision) {
|
|
230
|
+
case 0:
|
|
231
|
+
return DecimalPrecision.Zero;
|
|
232
|
+
case 1:
|
|
233
|
+
return DecimalPrecision.One;
|
|
234
|
+
case 2:
|
|
235
|
+
return DecimalPrecision.Two;
|
|
236
|
+
case 3:
|
|
237
|
+
return DecimalPrecision.Three;
|
|
238
|
+
case 4:
|
|
239
|
+
return DecimalPrecision.Four;
|
|
240
|
+
case 5:
|
|
241
|
+
return DecimalPrecision.Five;
|
|
242
|
+
case 6:
|
|
243
|
+
return DecimalPrecision.Six;
|
|
244
|
+
case 7:
|
|
245
|
+
return DecimalPrecision.Seven;
|
|
246
|
+
case 8:
|
|
247
|
+
return DecimalPrecision.Eight;
|
|
248
|
+
case 9:
|
|
249
|
+
return DecimalPrecision.Nine;
|
|
250
|
+
case 10:
|
|
251
|
+
return DecimalPrecision.Ten;
|
|
252
|
+
case 11:
|
|
253
|
+
return DecimalPrecision.Eleven;
|
|
254
|
+
case 12:
|
|
255
|
+
return DecimalPrecision.Twelve;
|
|
256
|
+
default:
|
|
257
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The 'precision' attribute must be an integer in the range 0-12.`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/** This method validates the input value, that is typically extracted for persisted JSON data, is a valid FractionalPrecision. Throws exception if not valid. */
|
|
261
|
+
static parseFractionalPrecision(jsonObjPrecision, formatName) {
|
|
262
|
+
switch (jsonObjPrecision) {
|
|
263
|
+
case 1:
|
|
264
|
+
return FractionalPrecision.One;
|
|
265
|
+
case 2:
|
|
266
|
+
return FractionalPrecision.Two;
|
|
267
|
+
case 4:
|
|
268
|
+
return FractionalPrecision.Four;
|
|
269
|
+
case 8:
|
|
270
|
+
return FractionalPrecision.Eight;
|
|
271
|
+
case 16:
|
|
272
|
+
return FractionalPrecision.Sixteen;
|
|
273
|
+
case 32:
|
|
274
|
+
return FractionalPrecision.ThirtyTwo;
|
|
275
|
+
case 64:
|
|
276
|
+
return FractionalPrecision.SixtyFour;
|
|
277
|
+
case 128:
|
|
278
|
+
return FractionalPrecision.OneHundredTwentyEight;
|
|
279
|
+
case 256:
|
|
280
|
+
return FractionalPrecision.TwoHundredFiftySix;
|
|
281
|
+
default:
|
|
282
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'precision' attribute.`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/** This method validates the input value, that is typically extracted for persisted JSON data, is a valid DecimalPrecision or FractionalPrecision. Throws exception if not valid. */
|
|
286
|
+
static parsePrecision(precision, formatName, type) {
|
|
287
|
+
switch (type) { // type must be decimal, fractional, scientific, or station
|
|
288
|
+
case FormatType.Decimal:
|
|
289
|
+
case FormatType.Scientific:
|
|
290
|
+
case FormatType.Station:
|
|
291
|
+
return Format.parseDecimalPrecision(precision);
|
|
292
|
+
case FormatType.Fractional:
|
|
293
|
+
return Format.parseFractionalPrecision(precision, formatName);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
verifyFormatTraitsOptions(formatTraitsFromJson) {
|
|
297
|
+
const formatTraits = (Array.isArray(formatTraitsFromJson)) ? formatTraitsFromJson : formatTraitsFromJson.split(/,|;|\|/);
|
|
298
|
+
formatTraits.forEach((formatTraitsString) => {
|
|
299
|
+
this._formatTraits = Format.parseFormatTrait(formatTraitsString, this.formatTraits);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/** This method returns true if the formatTrait is set in this Format object. */
|
|
303
|
+
hasFormatTraitSet(formatTrait) {
|
|
304
|
+
return (this._formatTraits & formatTrait) === formatTrait;
|
|
305
|
+
}
|
|
306
|
+
async createUnit(unitsProvider, name, label) {
|
|
307
|
+
if (name === undefined || typeof (name) !== "string" || (label !== undefined && typeof (label) !== "string")) // throws if name is undefined or name isn't a string or if label is defined and isn't a string
|
|
308
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `This Composite has a unit with an invalid 'name' or 'label' attribute.`);
|
|
309
|
+
for (const unit of this.units) {
|
|
310
|
+
const unitObj = unit[0].name;
|
|
311
|
+
if (unitObj.toLowerCase() === name.toLowerCase()) // duplicate names are not allowed
|
|
312
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The unit ${unitObj} has a duplicate name.`);
|
|
313
|
+
}
|
|
314
|
+
const newUnit = await unitsProvider.findUnitByName(name);
|
|
315
|
+
if (!newUnit || !newUnit.isValid)
|
|
316
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `Invalid unit name '${name}'.`);
|
|
317
|
+
this.units.push([newUnit, label]);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Clone Format
|
|
321
|
+
*/
|
|
322
|
+
clone(options) {
|
|
323
|
+
var _a;
|
|
324
|
+
const newFormat = new Format(this.name);
|
|
325
|
+
newFormat._roundFactor = this._roundFactor;
|
|
326
|
+
newFormat._type = this._type;
|
|
327
|
+
newFormat._precision = this._precision;
|
|
328
|
+
newFormat._minWidth = this._minWidth;
|
|
329
|
+
newFormat._scientificType = this._scientificType;
|
|
330
|
+
newFormat._showSignOption = this._showSignOption;
|
|
331
|
+
newFormat._decimalSeparator = this._decimalSeparator;
|
|
332
|
+
newFormat._thousandSeparator = this._thousandSeparator;
|
|
333
|
+
newFormat._uomSeparator = this._uomSeparator;
|
|
334
|
+
newFormat._stationSeparator = this._stationSeparator;
|
|
335
|
+
newFormat._stationOffsetSize = this._stationOffsetSize;
|
|
336
|
+
newFormat._formatTraits = this._formatTraits;
|
|
337
|
+
newFormat._spacer = this._spacer;
|
|
338
|
+
newFormat._includeZero = this._includeZero;
|
|
339
|
+
newFormat._customProps = this._customProps;
|
|
340
|
+
this._units && (newFormat._units = [...this._units]);
|
|
341
|
+
if (newFormat._units) {
|
|
342
|
+
if (options === null || options === void 0 ? void 0 : options.showOnlyPrimaryUnit) {
|
|
343
|
+
if (newFormat._units.length > 1)
|
|
344
|
+
newFormat._units.length = 1;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (undefined !== (options === null || options === void 0 ? void 0 : options.traits))
|
|
348
|
+
newFormat._formatTraits = options === null || options === void 0 ? void 0 : options.traits;
|
|
349
|
+
if (undefined !== (options === null || options === void 0 ? void 0 : options.type))
|
|
350
|
+
newFormat._type = options.type;
|
|
351
|
+
if (undefined !== (options === null || options === void 0 ? void 0 : options.precision)) {
|
|
352
|
+
// ensure specified precision is valid
|
|
353
|
+
const precision = Format.parsePrecision(options === null || options === void 0 ? void 0 : options.precision, "clone", newFormat._type);
|
|
354
|
+
newFormat._precision = precision;
|
|
355
|
+
}
|
|
356
|
+
if (undefined !== (options === null || options === void 0 ? void 0 : options.primaryUnit)) {
|
|
357
|
+
if (options.primaryUnit.unit) {
|
|
358
|
+
const newUnits = new Array();
|
|
359
|
+
newUnits.push([options.primaryUnit.unit, options.primaryUnit.label]);
|
|
360
|
+
newFormat._units = newUnits;
|
|
361
|
+
}
|
|
362
|
+
else if (options.primaryUnit.label && ((_a = newFormat._units) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
363
|
+
// update label only
|
|
364
|
+
newFormat._units[0][1] = options.primaryUnit.label;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return newFormat;
|
|
368
|
+
}
|
|
369
|
+
loadFormatProperties(jsonObj) {
|
|
370
|
+
if (isCustomFormatProps(jsonObj))
|
|
371
|
+
this._customProps = jsonObj.custom;
|
|
372
|
+
if (undefined === jsonObj.type) // type is required
|
|
373
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} does not have the required 'type' attribute.`);
|
|
374
|
+
if (typeof (jsonObj.type) !== "string")
|
|
375
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'type' attribute. It should be of type 'string'.`);
|
|
376
|
+
this._type = Format.parseFormatType(jsonObj.type, this.name);
|
|
377
|
+
if (undefined === jsonObj.precision) // precision is required
|
|
378
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} does not have the required 'precision' attribute.`);
|
|
379
|
+
else if (typeof (jsonObj.precision) !== "number") // must be a number
|
|
380
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'precision' attribute. It should be of type 'number'.`);
|
|
381
|
+
else if (!Number.isInteger(jsonObj.precision)) // must be an integer
|
|
382
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'precision' attribute. It should be an integer.`);
|
|
383
|
+
this._precision = Format.parsePrecision(jsonObj.precision, this.name, this._type);
|
|
384
|
+
if (this.type === FormatType.Scientific) {
|
|
385
|
+
if (undefined === jsonObj.scientificType) // if format type is scientific and scientific type is undefined, throw
|
|
386
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has type 'Scientific' therefore attribute 'scientificType' is required.`);
|
|
387
|
+
if (typeof (jsonObj.scientificType) !== "string")
|
|
388
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'scientificType' attribute. It should be of type 'string'.`);
|
|
389
|
+
this._scientificType = Format.parseScientificType(jsonObj.scientificType.toLowerCase(), this.name);
|
|
390
|
+
}
|
|
391
|
+
if (this.type === FormatType.Station) {
|
|
392
|
+
if (undefined === jsonObj.stationOffsetSize)
|
|
393
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has type 'Station' therefore attribute 'stationOffsetSize' is required.`);
|
|
394
|
+
if (typeof (jsonObj.stationOffsetSize) !== "number")
|
|
395
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'stationOffsetSize' attribute. It should be of type 'number'.`);
|
|
396
|
+
if (!Number.isInteger(jsonObj.stationOffsetSize) || jsonObj.stationOffsetSize <= 0) // must be a positive int > 0
|
|
397
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'stationOffsetSize' attribute. It should be a positive integer.`);
|
|
398
|
+
this._stationOffsetSize = jsonObj.stationOffsetSize;
|
|
399
|
+
}
|
|
400
|
+
if (undefined !== jsonObj.roundFactor) { // optional; default is 0.0
|
|
401
|
+
if (typeof (jsonObj.roundFactor) !== "number")
|
|
402
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'roundFactor' attribute. It should be of type 'number'.`);
|
|
403
|
+
if (jsonObj.roundFactor !== this.roundFactor) // if roundFactor isn't default value of 0.0, reassign roundFactor variable
|
|
404
|
+
this._roundFactor = jsonObj.roundFactor;
|
|
405
|
+
}
|
|
406
|
+
if (undefined !== jsonObj.minWidth) { // optional
|
|
407
|
+
if (typeof (jsonObj.minWidth) !== "number")
|
|
408
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'minWidth' attribute. It should be of type 'number'.`);
|
|
409
|
+
if (!Number.isInteger(jsonObj.minWidth) || jsonObj.minWidth < 0) // must be a positive int
|
|
410
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'minWidth' attribute. It should be a positive integer.`);
|
|
411
|
+
this._minWidth = jsonObj.minWidth;
|
|
412
|
+
}
|
|
413
|
+
if (undefined !== jsonObj.showSignOption) { // optional; default is "onlyNegative"
|
|
414
|
+
if (typeof (jsonObj.showSignOption) !== "string")
|
|
415
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'showSignOption' attribute. It should be of type 'string'.`);
|
|
416
|
+
this._showSignOption = Format.parseShowSignOption(jsonObj.showSignOption, this.name);
|
|
417
|
+
}
|
|
418
|
+
if (undefined !== jsonObj.formatTraits && jsonObj.formatTraits.length !== 0) { // FormatTraits is optional
|
|
419
|
+
if (!Array.isArray(jsonObj.formatTraits) && typeof (jsonObj.formatTraits) !== "string") // must be either an array of strings or a string
|
|
420
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'formatTraits' attribute. It should be of type 'string' or 'string[]'.`);
|
|
421
|
+
this.verifyFormatTraitsOptions(jsonObj.formatTraits); // check that all of the options for formatTraits are valid. If now, throw
|
|
422
|
+
}
|
|
423
|
+
if (undefined !== jsonObj.decimalSeparator) { // optional
|
|
424
|
+
if (typeof (jsonObj.decimalSeparator) !== "string") // not a string or not a one character string
|
|
425
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'decimalSeparator' attribute. It should be of type 'string'.`);
|
|
426
|
+
if (jsonObj.decimalSeparator.length !== 1)
|
|
427
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'decimalSeparator' attribute. It must be a one character string.`);
|
|
428
|
+
this._decimalSeparator = jsonObj.decimalSeparator;
|
|
429
|
+
}
|
|
430
|
+
if (undefined !== jsonObj.thousandSeparator) { // optional
|
|
431
|
+
if (typeof (jsonObj.thousandSeparator) !== "string")
|
|
432
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'thousandSeparator' attribute. It should be of type 'string'.`);
|
|
433
|
+
if (jsonObj.thousandSeparator.length !== 1)
|
|
434
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'thousandSeparator' attribute. It must be a one character string.`);
|
|
435
|
+
this._thousandSeparator = jsonObj.thousandSeparator;
|
|
436
|
+
}
|
|
437
|
+
if (undefined !== jsonObj.uomSeparator) { // optional; default is " "
|
|
438
|
+
if (typeof (jsonObj.uomSeparator) !== "string")
|
|
439
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'uomSeparator' attribute. It should be of type 'string'.`);
|
|
440
|
+
if (jsonObj.uomSeparator.length < 0 || jsonObj.uomSeparator.length > 1)
|
|
441
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'uomSeparator' attribute. It must be empty or a string with a single character.`);
|
|
442
|
+
this._uomSeparator = jsonObj.uomSeparator;
|
|
443
|
+
}
|
|
444
|
+
if (undefined !== jsonObj.stationSeparator) { // optional; default is "+"
|
|
445
|
+
if (typeof (jsonObj.stationSeparator) !== "string")
|
|
446
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'stationSeparator' attribute. It should be of type 'string'.`);
|
|
447
|
+
if (jsonObj.stationSeparator.length !== 1)
|
|
448
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'stationSeparator' attribute. It must be a one character string.`);
|
|
449
|
+
this._stationSeparator = jsonObj.stationSeparator;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Populates this Format with the values from the provided.
|
|
454
|
+
*/
|
|
455
|
+
async fromJSON(unitsProvider, jsonObj) {
|
|
456
|
+
this.loadFormatProperties(jsonObj);
|
|
457
|
+
if (undefined !== jsonObj.composite) { // optional
|
|
458
|
+
this._units = new Array();
|
|
459
|
+
if (jsonObj.composite.includeZero !== undefined) {
|
|
460
|
+
if (typeof (jsonObj.composite.includeZero) !== "boolean") // includeZero must be a boolean IF it is defined
|
|
461
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with an invalid 'includeZero' attribute. It should be of type 'boolean'.`);
|
|
462
|
+
this._includeZero = jsonObj.composite.includeZero;
|
|
463
|
+
}
|
|
464
|
+
if (jsonObj.composite.spacer !== undefined) { // spacer must be a string IF it is defined
|
|
465
|
+
if (typeof (jsonObj.composite.spacer) !== "string")
|
|
466
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with an invalid 'spacer' attribute. It must be of type 'string'.`);
|
|
467
|
+
if (jsonObj.composite.spacer.length < 0 || jsonObj.composite.spacer.length > 1)
|
|
468
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with an invalid 'spacer' attribute. It must be empty or a string with a single character.`);
|
|
469
|
+
this._spacer = jsonObj.composite.spacer;
|
|
470
|
+
}
|
|
471
|
+
if (jsonObj.composite.units !== undefined) { // if composite is defined, it must be an array with 1-4 units
|
|
472
|
+
if (!Array.isArray(jsonObj.composite.units)) { // must be an array
|
|
473
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with an invalid 'units' attribute. It must be of type 'array'`);
|
|
474
|
+
}
|
|
475
|
+
if (jsonObj.composite.units.length > 0 && jsonObj.composite.units.length <= 4) { // Composite requires 1-4 units
|
|
476
|
+
try {
|
|
477
|
+
const createUnitPromises = [];
|
|
478
|
+
for (const unit of jsonObj.composite.units) {
|
|
479
|
+
createUnitPromises.push(this.createUnit(unitsProvider, unit.name, unit.label));
|
|
480
|
+
}
|
|
481
|
+
await Promise.all(createUnitPromises);
|
|
482
|
+
}
|
|
483
|
+
catch (e) {
|
|
484
|
+
throw e;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (undefined === this.units || this.units.length === 0)
|
|
489
|
+
throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with no valid 'units'`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
/** Create a Format from FormatProps */
|
|
493
|
+
static async createFromJSON(name, unitsProvider, formatProps) {
|
|
494
|
+
const actualFormat = new Format(name);
|
|
495
|
+
await actualFormat.fromJSON(unitsProvider, formatProps);
|
|
496
|
+
return actualFormat;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Returns a JSON object that contain the specification for this Format.
|
|
500
|
+
*/
|
|
501
|
+
toJSON() {
|
|
502
|
+
let composite;
|
|
503
|
+
if (this.units) {
|
|
504
|
+
const units = this.units.map((value) => {
|
|
505
|
+
if (undefined !== value[1])
|
|
506
|
+
return { name: value[0].name, label: value[1] };
|
|
507
|
+
else
|
|
508
|
+
return { name: value[0].name };
|
|
509
|
+
});
|
|
510
|
+
composite = {
|
|
511
|
+
spacer: this.spacer,
|
|
512
|
+
includeZero: this.includeZero,
|
|
513
|
+
units,
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
if (this.customProps)
|
|
517
|
+
return {
|
|
518
|
+
type: Format.formatTypeToString(this.type),
|
|
519
|
+
precision: this.precision,
|
|
520
|
+
roundFactor: this.roundFactor,
|
|
521
|
+
minWidth: this.minWidth,
|
|
522
|
+
showSignOption: Format.showSignOptionToString(this.showSignOption),
|
|
523
|
+
formatTraits: Format.formatTraitsToArray(this.formatTraits),
|
|
524
|
+
decimalSeparator: this.decimalSeparator,
|
|
525
|
+
thousandSeparator: this.thousandSeparator,
|
|
526
|
+
uomSeparator: this.uomSeparator,
|
|
527
|
+
scientificType: this.scientificType ? Format.scientificTypeToString(this.scientificType) : undefined,
|
|
528
|
+
stationOffsetSize: this.stationOffsetSize,
|
|
529
|
+
stationSeparator: this.stationSeparator,
|
|
530
|
+
composite,
|
|
531
|
+
custom: this.customProps,
|
|
532
|
+
};
|
|
533
|
+
return {
|
|
534
|
+
type: Format.formatTypeToString(this.type),
|
|
535
|
+
precision: this.precision,
|
|
536
|
+
roundFactor: this.roundFactor,
|
|
537
|
+
minWidth: this.minWidth,
|
|
538
|
+
showSignOption: Format.showSignOptionToString(this.showSignOption),
|
|
539
|
+
formatTraits: Format.formatTraitsToArray(this.formatTraits),
|
|
540
|
+
decimalSeparator: this.decimalSeparator,
|
|
541
|
+
thousandSeparator: this.thousandSeparator,
|
|
542
|
+
uomSeparator: this.uomSeparator,
|
|
543
|
+
scientificType: this.scientificType ? Format.scientificTypeToString(this.scientificType) : undefined,
|
|
544
|
+
stationOffsetSize: this.stationOffsetSize,
|
|
545
|
+
stationSeparator: this.stationSeparator,
|
|
546
|
+
composite,
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
//# sourceMappingURL=Format.js.map
|