@lhncbc/ucum-lhc 4.2.0 → 5.0.0

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.
@@ -1617,24 +1617,17 @@ var UcumLhcUtils = /*#__PURE__*/function () {
1617
1617
  if (valConv === undefined) valConv = 'validate';
1618
1618
  var resp = this.getSpecifiedUnit(uStr, valConv, suggest);
1619
1619
  var theUnit = resp['unit'];
1620
- var retObj = {};
1621
-
1622
- if (!theUnit) {
1623
- retObj = {
1624
- 'status': !resp['origString'] || resp['origString'] === null ? 'error' : 'invalid',
1625
- 'ucumCode': null
1626
- };
1627
- } else {
1628
- retObj = {
1629
- 'status': resp['origString'] === uStr ? 'valid' : 'invalid',
1630
- 'ucumCode': resp['origString'],
1631
- 'unit': {
1632
- 'code': theUnit.csCode_,
1633
- 'name': theUnit.name_,
1634
- 'guidance': theUnit.guidance_
1635
- }
1636
- };
1637
- }
1620
+ var retObj = !theUnit ? {
1621
+ 'ucumCode': null
1622
+ } : {
1623
+ 'ucumCode': resp['origString'],
1624
+ 'unit': {
1625
+ 'code': theUnit.csCode_,
1626
+ 'name': theUnit.name_,
1627
+ 'guidance': theUnit.guidance_
1628
+ }
1629
+ };
1630
+ retObj.status = resp.status;
1638
1631
 
1639
1632
  if (resp['suggestions']) {
1640
1633
  retObj['suggestions'] = resp['suggestions'];
@@ -1723,10 +1716,7 @@ var UcumLhcUtils = /*#__PURE__*/function () {
1723
1716
  returnObj['msg'].push('No "from" unit expression specified.');
1724
1717
  }
1725
1718
 
1726
- if (fromVal === null || isNaN(fromVal) || typeof fromVal !== 'number' && !intUtils_.isNumericString(fromVal)) {
1727
- returnObj['status'] = 'error';
1728
- returnObj['msg'].push('No "from" value, or an invalid "from" value, ' + 'was specified.');
1729
- }
1719
+ this._checkFromVal(fromVal, returnObj);
1730
1720
 
1731
1721
  if (toUnitCode) {
1732
1722
  toUnitCode = toUnitCode.trim();
@@ -1823,11 +1813,17 @@ var UcumLhcUtils = /*#__PURE__*/function () {
1823
1813
  * @param fromUnit the unit string to be converted to base units information
1824
1814
  * @param fromVal the number of "from" units to be converted
1825
1815
  * @returns an object with the properties:
1816
+ * 'status' indicates whether the result succeeded. The value will be one of:
1817
+ * 'succeeded': the conversion was successfully calculated (which can be
1818
+ * true even if it was already in base units);
1819
+ * 'invalid': fromUnit is not a valid UCUM code;
1820
+ * 'failed': the conversion could not be made (e.g., if it is an "arbitrary" unit);
1821
+ * 'error': if an error occurred (an input or programming error)
1826
1822
  * 'msg': an array of one or more messages, if the string is invalid or
1827
1823
  * an error occurred, indicating the problem, or a suggestion of a
1828
1824
  * substitution such as the substitution of 'G' for 'Gauss', or
1829
- * an empty array if no messages were generated. If this is not empty,
1830
- * no other information will be returned.
1825
+ * an empty array if no messages were generated. There can also be a
1826
+ * message that is just informational or warning.
1831
1827
  * 'magnitude': the new value when fromVal units of fromUnits is expressed in the base units.
1832
1828
  * 'fromUnitIsSpecial': whether the input unit fromUnit is a "special unit"
1833
1829
  * as defined in UCUM. This means there is some function applied to convert
@@ -1840,58 +1836,91 @@ var UcumLhcUtils = /*#__PURE__*/function () {
1840
1836
  }, {
1841
1837
  key: "convertToBaseUnits",
1842
1838
  value: function convertToBaseUnits(fromUnit, fromVal) {
1843
- var inputUnitLookup = this.getSpecifiedUnit(fromUnit, 'validate');
1844
1839
  var retObj = {};
1845
- var unit = inputUnitLookup.unit;
1846
- retObj.msg = inputUnitLookup.retMsg || [];
1847
1840
 
1848
- if (!unit) {
1849
- var _inputUnitLookup$retM;
1841
+ this._checkFromVal(fromVal, retObj);
1842
+
1843
+ if (!retObj.status) {
1844
+ // could be set to 'error' by _checkFromVal
1845
+ var inputUnitLookup = this.getSpecifiedUnit(fromUnit, 'validate');
1846
+ retObj = {
1847
+ status: inputUnitLookup.status == 'valid' ? 'succeeded' : inputUnitLookup.status
1848
+ };
1849
+ var unit = inputUnitLookup.unit;
1850
+ retObj.msg = inputUnitLookup.retMsg || [];
1851
+
1852
+ if (!unit) {
1853
+ var _inputUnitLookup$retM;
1850
1854
 
1851
- if (((_inputUnitLookup$retM = inputUnitLookup.retMsg) === null || _inputUnitLookup$retM === void 0 ? void 0 : _inputUnitLookup$retM.length) == 0) retObj.msg.push('Could not find unit information for ' + fromUnit);
1852
- } else if (unit.isArbitrary_) {
1853
- retObj.msg.push('Arbitrary units cannot be converted to base units or other units.');
1854
- } else if (retObj.msg.length == 0) {
1855
- var _unit$dim_, _retUnitLookup$retMsg;
1855
+ if (((_inputUnitLookup$retM = inputUnitLookup.retMsg) === null || _inputUnitLookup$retM === void 0 ? void 0 : _inputUnitLookup$retM.length) == 0) retObj.msg.push('Could not find unit information for ' + fromUnit);
1856
+ } else if (unit.isArbitrary_) {
1857
+ retObj.msg.push('Arbitrary units cannot be converted to base units or other units.');
1858
+ retObj.status = 'failed';
1859
+ } else if (retObj.status == 'succeeded') {
1860
+ var _unit$dim_;
1856
1861
 
1857
- var unitToExp = {};
1858
- var dimVec = (_unit$dim_ = unit.dim_) === null || _unit$dim_ === void 0 ? void 0 : _unit$dim_.dimVec_;
1859
- var baseUnitString = '1';
1862
+ var unitToExp = {};
1863
+ var dimVec = (_unit$dim_ = unit.dim_) === null || _unit$dim_ === void 0 ? void 0 : _unit$dim_.dimVec_;
1864
+ var baseUnitString = '1';
1860
1865
 
1861
- if (dimVec) {
1862
- var dimVecIndexToBaseUnit = UnitTables.getInstance().dimVecIndexToBaseUnit_;
1866
+ if (dimVec) {
1867
+ var dimVecIndexToBaseUnit = UnitTables.getInstance().dimVecIndexToBaseUnit_;
1863
1868
 
1864
- for (var i = 0, len = dimVec.length; i < len; ++i) {
1865
- var exp = dimVec[i];
1869
+ for (var i = 0, len = dimVec.length; i < len; ++i) {
1870
+ var exp = dimVec[i];
1866
1871
 
1867
- if (exp) {
1868
- unitToExp[dimVecIndexToBaseUnit[i]] = exp;
1869
- baseUnitString += '.' + dimVecIndexToBaseUnit[i] + exp;
1872
+ if (exp) {
1873
+ unitToExp[dimVecIndexToBaseUnit[i]] = exp;
1874
+ baseUnitString += '.' + dimVecIndexToBaseUnit[i] + exp;
1875
+ }
1870
1876
  }
1871
- }
1872
- } // The unit might have a conversion function, which has to be applied; we
1873
- // cannot just assume unit_.magnitude_ is the magnitude in base units.
1877
+ } // The unit might have a conversion function, which has to be applied; we
1878
+ // cannot just assume unit_.magnitude_ is the magnitude in base units.
1874
1879
 
1875
1880
 
1876
- var retUnitLookup = this.getSpecifiedUnit(baseUnitString, 'validate'); // There should not be any error in retUnitLookup, unless there is a bug.
1881
+ var retUnitLookup = this.getSpecifiedUnit(baseUnitString, 'validate'); // There should not be any error in retUnitLookup, unless there is a bug.
1877
1882
 
1878
- var retUnit = retUnitLookup.unit;
1879
- if (!retUnit && ((_retUnitLookup$retMsg = retUnitLookup.retMsg) === null || _retUnitLookup$retMsg === void 0 ? void 0 : _retUnitLookup$retMsg.length) == 0) retObj.msg.push('Unable construct base unit string; tried ' + baseUnitString);else {
1880
- try {
1881
- retObj.magnitude = retUnit.convertFrom(fromVal, unit);
1882
- } catch (e) {
1883
- retObj.msg.push(e.toString());
1884
- }
1883
+ var retUnit = retUnitLookup.unit;
1885
1884
 
1886
- if (retObj.msg.length == 0) {
1887
- retObj.unitToExp = unitToExp;
1888
- retObj.fromUnitIsSpecial = unit.isSpecial_;
1885
+ if (retUnitLookup.status !== 'valid') {
1886
+ retObj.msg.push('Unable construct base unit string; tried ' + baseUnitString);
1887
+ retObj.status = 'error';
1888
+ } else {
1889
+ try {
1890
+ retObj.magnitude = retUnit.convertFrom(fromVal, unit);
1891
+ } catch (e) {
1892
+ retObj.msg.push(e.toString());
1893
+ retObj.status = 'error';
1894
+ }
1895
+
1896
+ if (retObj.status == 'succeeded') {
1897
+ retObj.unitToExp = unitToExp;
1898
+ retObj.fromUnitIsSpecial = unit.isSpecial_;
1899
+ }
1889
1900
  }
1890
1901
  }
1891
1902
  }
1892
1903
 
1893
1904
  return retObj;
1894
1905
  }
1906
+ /**
1907
+ * Checks the given value as to whether it is suitable as a "from" value in a
1908
+ * unit conversion. If it is not, the responseObj will have its status set
1909
+ * to 'error' and a message added.
1910
+ * @param fromVal The value to check
1911
+ * @param responseObj the object that will be updated if the value is not
1912
+ * usable.
1913
+ */
1914
+
1915
+ }, {
1916
+ key: "_checkFromVal",
1917
+ value: function _checkFromVal(fromVal, responseObj) {
1918
+ if (fromVal === null || isNaN(fromVal) || typeof fromVal !== 'number' && !intUtils_.isNumericString(fromVal)) {
1919
+ responseObj.status = 'error';
1920
+ if (!responseObj.msg) responseObj.msg = [];
1921
+ responseObj.msg.push('No "from" value, or an invalid "from" value, ' + 'was specified.');
1922
+ }
1923
+ }
1895
1924
  /**
1896
1925
  * This method accepts a term and looks for units that include it as
1897
1926
  * a synonym - or that include the term in its name.
@@ -1937,13 +1966,18 @@ var UcumLhcUtils = /*#__PURE__*/function () {
1937
1966
  * true indicates suggestions are wanted; false indicates they are not,
1938
1967
  * and is the default if the parameter is not specified;
1939
1968
  * @returns a hash containing:
1969
+ * 'status' will be 'valid' (uName is a valid UCUM code), 'invalid'
1970
+ * (the uStr is not a valid UCUM code, and substitutions or
1971
+ * suggestions may or may not be returned, depending on what was
1972
+ * requested and found); or 'error' (an input or programming error
1973
+ * occurred);
1940
1974
  * 'unit' the unit object (or null if there were problems creating the
1941
1975
  * unit);
1942
1976
  * 'origString' the possibly updated unit string passed in;
1943
1977
  * 'retMsg' an array of user messages (informational, error or warning) if
1944
1978
  * any were generated (IF any were generated, otherwise will be an
1945
1979
  * empty array); and
1946
- * 'suggestions' is an array of 1 or more hash objects. Each hash
1980
+ * 'suggestions' is an array of 1 or more hash objects. Each hash
1947
1981
  * contains three elements:
1948
1982
  * 'msg' which is a message indicating what unit expression the
1949
1983
  * suggestions are for;
@@ -1990,7 +2024,17 @@ var UcumLhcUtils = /*#__PURE__*/function () {
1990
2024
  } // end if the unit was not found as a unit name
1991
2025
 
1992
2026
  } // end if a unit expression was specified
2027
+ // Set the status field
2028
+
1993
2029
 
2030
+ if (!retObj.unit) {
2031
+ // No unit was found; check whether origString has a value
2032
+ retObj.status = !retObj.origString ? 'error' : 'invalid';
2033
+ } else {
2034
+ // Check whether substitutions were made to the unit string in order to
2035
+ // find the unit
2036
+ retObj.status = retObj.origString === uName ? 'valid' : 'invalid';
2037
+ }
1994
2038
 
1995
2039
  return retObj;
1996
2040
  } // end getSpecifiedUnit
@@ -4459,24 +4503,30 @@ var UnitString = /*#__PURE__*/function () {
4459
4503
  if (!befAnnoText && !aftAnnoText) {
4460
4504
  var tryBrackets = '[' + annoText.substring(1, annoText.length - 1) + ']';
4461
4505
 
4462
- var mkUnitRet = this._makeUnit(tryBrackets, origString); // If we got back a unit, assign it to the returned unit, and add
4463
- // a message to advise the user that brackets should enclose the code
4506
+ var mkUnitRet = this._makeUnit(tryBrackets, origString); // Nearly anything inside braces is valid, so we don't want to change the
4507
+ // unit, but we can put the found unit in the message as a sort of
4508
+ // warning.
4464
4509
 
4465
4510
 
4466
4511
  if (mkUnitRet[0]) {
4467
- retUnit = mkUnitRet[0];
4468
- origString = origString.replace(annoText, tryBrackets);
4469
- this.retMsg_.push("".concat(annoText, " is not a valid unit expression, but ") + "".concat(tryBrackets, " is.\n") + this.vcMsgStart_ + "".concat(tryBrackets, " (").concat(retUnit.name_, ")").concat(this.vcMsgEnd_));
4470
- } // Otherwise assume that this should be interpreted as a 1
4471
- else {
4472
- // remove error message generated for trybrackets
4473
- if (this.retMsg_.length > msgLen) {
4474
- this.retMsg_.pop();
4475
- }
4476
-
4477
- uCode = 1;
4478
- retUnit = 1;
4512
+ retUnit = uCode;
4513
+ this.retMsg_.push("".concat(annoText, " is a valid unit expression, but ") + "did you mean ".concat(tryBrackets, " (").concat(mkUnitRet[0].name_, ")?"));
4514
+ } else {
4515
+ // remove error message generated for trybrackets
4516
+ if (this.retMsg_.length > msgLen) {
4517
+ this.retMsg_.pop();
4479
4518
  }
4519
+ } // This is the case where the string is only this annotation.
4520
+ // Create and return a unit object, as we do for numeric units in
4521
+ // parseString.
4522
+
4523
+
4524
+ retUnit = new Unit({
4525
+ 'csCode_': annoText,
4526
+ 'ciCode_': annoText,
4527
+ 'magnitude_': 1,
4528
+ 'name_': annoText
4529
+ });
4480
4530
  } // end if it's only an annotation
4481
4531
  else {
4482
4532
  // if there's text before and no text after, assume the text before
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lhncbc/ucum-lhc",
3
- "version": "4.2.0",
3
+ "version": "5.0.0",
4
4
  "description": "Implements Unified Code for Units of Measure (UCUM) functions in a javascript library",
5
5
  "main": "source-cjs/ucumPkg.js",
6
6
  "homepage": "https://lhncbc.github.io/ucum-lhc/",
@@ -130,19 +130,12 @@ export class UcumLhcUtils {
130
130
 
131
131
  let resp = this.getSpecifiedUnit(uStr, valConv, suggest);
132
132
  let theUnit = resp['unit'];
133
- let retObj = {};
134
- if (!theUnit) {
135
- retObj = {'status': (!resp['origString'] || resp['origString'] === null) ?
136
- 'error' : 'invalid',
137
- 'ucumCode': null};
138
- }
139
- else {
140
- retObj = {'status': resp['origString'] === uStr ? 'valid': 'invalid',
141
- 'ucumCode': resp['origString'],
142
- 'unit': {'code': theUnit.csCode_,
143
- 'name': theUnit.name_,
144
- 'guidance': theUnit.guidance_ }};
145
- }
133
+ let retObj = !theUnit ? {'ucumCode': null} :
134
+ {'ucumCode': resp['origString'],
135
+ 'unit': {'code': theUnit.csCode_,
136
+ 'name': theUnit.name_,
137
+ 'guidance': theUnit.guidance_ }};
138
+ retObj.status = resp.status;
146
139
  if (resp['suggestions']) {
147
140
  retObj['suggestions'] = resp['suggestions'];
148
141
  }
@@ -228,12 +221,7 @@ export class UcumLhcUtils {
228
221
  returnObj['status'] = 'error';
229
222
  returnObj['msg'].push('No "from" unit expression specified.');
230
223
  }
231
- if (fromVal === null || isNaN(fromVal) || (typeof fromVal !== 'number' &&
232
- !intUtils_.isNumericString(fromVal))) {
233
- returnObj['status'] = 'error';
234
- returnObj['msg'].push('No "from" value, or an invalid "from" value, ' +
235
- 'was specified.');
236
- }
224
+ this._checkFromVal(fromVal, returnObj);
237
225
  if (toUnitCode) {
238
226
  toUnitCode = toUnitCode.trim();
239
227
  }
@@ -343,11 +331,17 @@ export class UcumLhcUtils {
343
331
  * @param fromUnit the unit string to be converted to base units information
344
332
  * @param fromVal the number of "from" units to be converted
345
333
  * @returns an object with the properties:
334
+ * 'status' indicates whether the result succeeded. The value will be one of:
335
+ * 'succeeded': the conversion was successfully calculated (which can be
336
+ * true even if it was already in base units);
337
+ * 'invalid': fromUnit is not a valid UCUM code;
338
+ * 'failed': the conversion could not be made (e.g., if it is an "arbitrary" unit);
339
+ * 'error': if an error occurred (an input or programming error)
346
340
  * 'msg': an array of one or more messages, if the string is invalid or
347
341
  * an error occurred, indicating the problem, or a suggestion of a
348
342
  * substitution such as the substitution of 'G' for 'Gauss', or
349
- * an empty array if no messages were generated. If this is not empty,
350
- * no other information will be returned.
343
+ * an empty array if no messages were generated. There can also be a
344
+ * message that is just informational or warning.
351
345
  * 'magnitude': the new value when fromVal units of fromUnits is expressed in the base units.
352
346
  * 'fromUnitIsSpecial': whether the input unit fromUnit is a "special unit"
353
347
  * as defined in UCUM. This means there is some function applied to convert
@@ -357,49 +351,57 @@ export class UcumLhcUtils {
357
351
  * 'unitToExp': a map of base units in uStr to their exponent
358
352
  */
359
353
  convertToBaseUnits(fromUnit, fromVal) {
360
- let inputUnitLookup = this.getSpecifiedUnit(fromUnit, 'validate');
361
354
  let retObj = {};
362
- let unit = inputUnitLookup.unit;
363
- retObj.msg = inputUnitLookup.retMsg || [];
364
- if (!unit) {
365
- if (inputUnitLookup.retMsg?.length == 0)
366
- retObj.msg.push('Could not find unit information for '+fromUnit);
367
- }
368
- else if (unit.isArbitrary_) {
369
- retObj.msg.push('Arbitrary units cannot be converted to base units or other units.');
370
- }
371
- else if (retObj.msg.length == 0) {
372
- let unitToExp = {};
373
- let dimVec = unit.dim_?.dimVec_
374
- let baseUnitString = '1';
375
- if (dimVec) {
376
- let dimVecIndexToBaseUnit = UnitTables.getInstance().dimVecIndexToBaseUnit_;
377
- for (let i=0, len=dimVec.length; i<len; ++i) {
378
- let exp = dimVec[i];
379
- if (exp) {
380
- unitToExp[dimVecIndexToBaseUnit[i]] = exp;
381
- baseUnitString += '.' + dimVecIndexToBaseUnit[i] + exp;
355
+ this._checkFromVal(fromVal, retObj);
356
+ if (!retObj.status) { // could be set to 'error' by _checkFromVal
357
+ let inputUnitLookup = this.getSpecifiedUnit(fromUnit, 'validate');
358
+ retObj = {status: inputUnitLookup.status == 'valid' ? 'succeeded' : inputUnitLookup.status};
359
+ let unit = inputUnitLookup.unit;
360
+ retObj.msg = inputUnitLookup.retMsg || [];
361
+ if (!unit) {
362
+ if (inputUnitLookup.retMsg?.length == 0)
363
+ retObj.msg.push('Could not find unit information for '+fromUnit);
364
+ }
365
+ else if (unit.isArbitrary_) {
366
+ retObj.msg.push('Arbitrary units cannot be converted to base units or other units.');
367
+ retObj.status = 'failed';
368
+ }
369
+ else if (retObj.status == 'succeeded') {
370
+ let unitToExp = {};
371
+ let dimVec = unit.dim_?.dimVec_
372
+ let baseUnitString = '1';
373
+ if (dimVec) {
374
+ let dimVecIndexToBaseUnit = UnitTables.getInstance().dimVecIndexToBaseUnit_;
375
+ for (let i=0, len=dimVec.length; i<len; ++i) {
376
+ let exp = dimVec[i];
377
+ if (exp) {
378
+ unitToExp[dimVecIndexToBaseUnit[i]] = exp;
379
+ baseUnitString += '.' + dimVecIndexToBaseUnit[i] + exp;
380
+ }
382
381
  }
383
382
  }
384
- }
385
383
 
386
- // The unit might have a conversion function, which has to be applied; we
387
- // cannot just assume unit_.magnitude_ is the magnitude in base units.
388
- let retUnitLookup = this.getSpecifiedUnit(baseUnitString, 'validate');
389
- // There should not be any error in retUnitLookup, unless there is a bug.
390
- let retUnit = retUnitLookup.unit;
391
- if (!retUnit && retUnitLookup.retMsg?.length == 0)
392
- retObj.msg.push('Unable construct base unit string; tried '+baseUnitString);
393
- else {
394
- try {
395
- retObj.magnitude = retUnit.convertFrom(fromVal, unit);
396
- }
397
- catch (e) {
398
- retObj.msg.push(e.toString());
384
+ // The unit might have a conversion function, which has to be applied; we
385
+ // cannot just assume unit_.magnitude_ is the magnitude in base units.
386
+ let retUnitLookup = this.getSpecifiedUnit(baseUnitString, 'validate');
387
+ // There should not be any error in retUnitLookup, unless there is a bug.
388
+ let retUnit = retUnitLookup.unit;
389
+ if (retUnitLookup.status !== 'valid') {
390
+ retObj.msg.push('Unable construct base unit string; tried '+baseUnitString);
391
+ retObj.status = 'error';
399
392
  }
400
- if (retObj.msg.length == 0) {
401
- retObj.unitToExp = unitToExp;
402
- retObj.fromUnitIsSpecial = unit.isSpecial_;
393
+ else {
394
+ try {
395
+ retObj.magnitude = retUnit.convertFrom(fromVal, unit);
396
+ }
397
+ catch (e) {
398
+ retObj.msg.push(e.toString());
399
+ retObj.status = 'error';
400
+ }
401
+ if (retObj.status == 'succeeded') {
402
+ retObj.unitToExp = unitToExp;
403
+ retObj.fromUnitIsSpecial = unit.isSpecial_;
404
+ }
403
405
  }
404
406
  }
405
407
  }
@@ -407,6 +409,26 @@ export class UcumLhcUtils {
407
409
  }
408
410
 
409
411
 
412
+ /**
413
+ * Checks the given value as to whether it is suitable as a "from" value in a
414
+ * unit conversion. If it is not, the responseObj will have its status set
415
+ * to 'error' and a message added.
416
+ * @param fromVal The value to check
417
+ * @param responseObj the object that will be updated if the value is not
418
+ * usable.
419
+ */
420
+ _checkFromVal(fromVal, responseObj) {
421
+ if (fromVal === null || isNaN(fromVal) || (typeof fromVal !== 'number' &&
422
+ !intUtils_.isNumericString(fromVal))) {
423
+ responseObj.status = 'error';
424
+ if (!responseObj.msg)
425
+ responseObj.msg = [];
426
+ responseObj.msg.push('No "from" value, or an invalid "from" value, ' +
427
+ 'was specified.');
428
+ }
429
+ }
430
+
431
+
410
432
  /**
411
433
  * This method accepts a term and looks for units that include it as
412
434
  * a synonym - or that include the term in its name.
@@ -450,13 +472,18 @@ export class UcumLhcUtils {
450
472
  * true indicates suggestions are wanted; false indicates they are not,
451
473
  * and is the default if the parameter is not specified;
452
474
  * @returns a hash containing:
475
+ * 'status' will be 'valid' (uName is a valid UCUM code), 'invalid'
476
+ * (the uStr is not a valid UCUM code, and substitutions or
477
+ * suggestions may or may not be returned, depending on what was
478
+ * requested and found); or 'error' (an input or programming error
479
+ * occurred);
453
480
  * 'unit' the unit object (or null if there were problems creating the
454
481
  * unit);
455
482
  * 'origString' the possibly updated unit string passed in;
456
483
  * 'retMsg' an array of user messages (informational, error or warning) if
457
484
  * any were generated (IF any were generated, otherwise will be an
458
485
  * empty array); and
459
- * 'suggestions' is an array of 1 or more hash objects. Each hash
486
+ * 'suggestions' is an array of 1 or more hash objects. Each hash
460
487
  * contains three elements:
461
488
  * 'msg' which is a message indicating what unit expression the
462
489
  * suggestions are for;
@@ -511,6 +538,17 @@ export class UcumLhcUtils {
511
538
  } // end if the unit was not found as a unit name
512
539
  } // end if a unit expression was specified
513
540
 
541
+ // Set the status field
542
+ if (!retObj.unit) {
543
+ // No unit was found; check whether origString has a value
544
+ retObj.status = !retObj.origString ? 'error' : 'invalid';
545
+ }
546
+ else {
547
+ // Check whether substitutions were made to the unit string in order to
548
+ // find the unit
549
+ retObj.status = retObj.origString === uName ? 'valid': 'invalid';
550
+ }
551
+
514
552
  return retObj;
515
553
 
516
554
  } // end getSpecifiedUnit
@@ -582,7 +620,3 @@ export class UcumLhcUtils {
582
620
  UcumLhcUtils.getInstance = function(){
583
621
  return new UcumLhcUtils();
584
622
  } ;
585
-
586
-
587
-
588
-
@@ -1330,24 +1330,31 @@ export class UnitString {
1330
1330
  let tryBrackets = '[' + annoText.substring(1, annoText.length - 1) + ']';
1331
1331
  let mkUnitRet = this._makeUnit(tryBrackets, origString);
1332
1332
 
1333
- // If we got back a unit, assign it to the returned unit, and add
1334
- // a message to advise the user that brackets should enclose the code
1333
+ // Nearly anything inside braces is valid, so we don't want to change the
1334
+ // unit, but we can put the found unit in the message as a sort of
1335
+ // warning.
1335
1336
  if (mkUnitRet[0]) {
1336
- retUnit = mkUnitRet[0];
1337
- origString = origString.replace(annoText, tryBrackets);
1338
- this.retMsg_.push(`${annoText} is not a valid unit expression, but ` +
1339
- `${tryBrackets} is.\n` + this.vcMsgStart_ +
1340
- `${tryBrackets} (${retUnit.name_})${this.vcMsgEnd_}`);
1337
+ retUnit = uCode;
1338
+ this.retMsg_.push(`${annoText} is a valid unit expression, but ` +
1339
+ `did you mean ${tryBrackets} (${mkUnitRet[0].name_})?`);
1341
1340
  }
1342
- // Otherwise assume that this should be interpreted as a 1
1343
1341
  else {
1344
1342
  // remove error message generated for trybrackets
1345
1343
  if (this.retMsg_.length > msgLen) {
1346
1344
  this.retMsg_.pop();
1347
1345
  }
1348
- uCode = 1;
1349
- retUnit = 1;
1350
1346
  }
1347
+
1348
+ // This is the case where the string is only this annotation.
1349
+ // Create and return a unit object, as we do for numeric units in
1350
+ // parseString.
1351
+ retUnit = new Unit({
1352
+ 'csCode_': annoText,
1353
+ 'ciCode_': annoText,
1354
+ 'magnitude_': 1,
1355
+ 'name_': annoText
1356
+ });
1357
+
1351
1358
  } // end if it's only an annotation
1352
1359
 
1353
1360
  else {