@itwin/ecschema-metadata
Version:
ECObjects core concepts in typescript
199 lines • 9.68 kB
JavaScript
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Metadata
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.OverrideFormat = void 0;
exports.getFormatProps = getFormatProps;
const XmlSerializationUtils_1 = require("../Deserialization/XmlSerializationUtils");
const ECObjects_1 = require("../ECObjects");
const core_quantity_1 = require("@itwin/core-quantity");
const Exception_1 = require("../Exception");
/**
* Overrides of a Format, from a Schema, and is SchemaItem that is used specifically on KindOfQuantity.
* @public @preview
*/
class OverrideFormat {
_precision;
_units;
/** The Format that this OverrideFormat is extending */
parent;
/** The name of this OverrideFormat.
*
* This should be set to the [FormatString]($docs/bis/ec/kindofquantity/#format-string) which represents the format override.
*/
name;
/** @internal */
constructor(parent, precision, unitAndLabels) {
this.parent = parent;
this.name = OverrideFormat.createOverrideFormatFullName(parent, precision, unitAndLabels);
this._precision = precision;
this._units = unitAndLabels;
}
// Properties that can be overriden
get precision() {
return (undefined === this._precision) ? this.parent.precision : this._precision;
}
get units() {
return (undefined === this._units) ? this.parent.units : this._units;
}
// Properties that cannot be overriden
get fullName() { return this.name; }
get roundFactor() { return this.parent.roundFactor; }
get type() { return this.parent.type; }
get minWidth() { return this.parent.minWidth; }
get scientificType() { return this.parent.scientificType; }
get showSignOption() { return this.parent.showSignOption; }
get decimalSeparator() { return this.parent.decimalSeparator; }
get thousandSeparator() { return this.parent.thousandSeparator; }
get uomSeparator() { return this.parent.uomSeparator; }
get stationSeparator() { return this.parent.stationSeparator; }
get stationOffsetSize() { return this.parent.stationOffsetSize; }
get formatTraits() { return this.parent.formatTraits; }
get spacer() { return this.parent.spacer; }
get includeZero() { return this.parent.includeZero; }
hasFormatTrait(formatTrait) {
return (this.parent.formatTraits & formatTrait) === formatTrait;
}
/** Returns the format string of this override in the Xml full name format.
* @internal
*/
fullNameXml(koqSchema) {
let fullName = XmlSerializationUtils_1.XmlSerializationUtils.createXmlTypedName(koqSchema, this.parent.schema, this.parent.name);
if (undefined !== this.precision)
fullName += `(${this.precision.toString()})`;
if (undefined === this._units)
return fullName;
for (const [unit, unitLabel] of this._units) {
const unitSchema = koqSchema.context.getSchemaSync(unit.schemaKey);
if (unitSchema === undefined)
throw new Exception_1.ECSchemaError(Exception_1.ECSchemaStatus.InvalidECJson, `The unit schema ${unit.schemaKey} is not found in the context.`);
fullName += "[";
fullName += XmlSerializationUtils_1.XmlSerializationUtils.createXmlTypedName(koqSchema, unitSchema, unit.name);
if (unitLabel !== undefined)
fullName += `|${unitLabel}`;
fullName += `]`;
}
return fullName;
}
/**
* Creates a valid OverrideFormat fullName from the parent Format and overridden units.
* @param parent The parent Format.
* @param unitAndLabels The overridden unit and labels collection.
*/
static createOverrideFormatFullName(parent, precision, unitAndLabels) {
let fullName = parent.fullName;
if (precision)
fullName += `(${precision.toString()})`;
if (undefined === unitAndLabels)
return fullName;
for (const [unit, unitLabel] of unitAndLabels)
if (undefined === unitLabel)
fullName += `[${unit.fullName}]`;
else
fullName += `[${unit.fullName}|${unitLabel}]`;
return fullName;
}
/** Parses the format string into the parts that make up an Override Format
* @param formatString
*/
static parseFormatString(formatString) {
const match = formatString.split(core_quantity_1.formatStringRgx); // split string based on regex groups
if (undefined === match[1])
throw new Exception_1.ECSchemaError(Exception_1.ECSchemaStatus.InvalidECJson, `The format string, ${formatString}, on KindOfQuantity is missing a format.`);
let precision;
if (undefined !== match[2] && undefined !== match[3]) {
const overrideString = match[2];
const tokens = [];
let prevPos = 1; // Initial position is the character directly after the opening '(' in the override string.
let currPos;
// TODO need to include `,` as a valid search argument.
while (-1 !== (currPos = overrideString.indexOf(")", prevPos))) {
tokens.push(overrideString.substring(prevPos, currPos));
prevPos = currPos + 1;
}
if (overrideString.length > 0 && undefined === tokens.find((token) => {
return "" !== token; // there is at least one token that is not empty.
})) {
throw new Exception_1.ECSchemaError(Exception_1.ECSchemaStatus.InvalidECJson, ``);
}
// The first override parameter overrides the default precision of the format
const precisionIndx = 0;
if (tokens.length >= precisionIndx + 1) {
if (tokens[precisionIndx].length > 0) {
precision = Number.parseInt(tokens[precisionIndx], 10);
if (Number.isNaN(precision))
throw new Exception_1.ECSchemaError(Exception_1.ECSchemaStatus.InvalidECJson, `The format string '${formatString}' on KindOfQuantity has a precision override '${tokens[precisionIndx]}' that is not number.`);
}
}
}
let i = 4;
let unitAndLabels;
while (i < match.length - 1) { // The regex match ends with an empty last value, which causes problems when exactly 4 unit overrides as specified, so ignore this last empty value
if (undefined === match[i])
break;
// Unit override required
if (undefined === match[i + 1])
throw new Exception_1.ECSchemaError(Exception_1.ECSchemaStatus.InvalidECJson, ``);
if (undefined === unitAndLabels)
unitAndLabels = [];
if (undefined !== match[i + 2]) // matches '|'
unitAndLabels.push([match[i + 1], match[i + 3] ?? ""]); // add unit name and label override (if '|' matches and next value is undefined, save it as an empty string)
else
unitAndLabels.push([match[i + 1], undefined]); // add unit name
i += 4;
}
return { name: match[1], precision, unitAndLabels };
}
/**
* @internal
*/
static isOverrideFormat(format) {
const overrideFormat = format;
return overrideFormat !== undefined && overrideFormat.name !== undefined && overrideFormat.parent !== undefined && overrideFormat.parent.schemaItemType === ECObjects_1.SchemaItemType.Format;
}
/**
* Returns a JSON object that contains the specification for the OverrideFormat where the precision and units properties have been overriden.
* If the precision and/or units properties have been overriden, the returned object will contain a "name" and a "parent" property.
* The "name" property identifies the OverrideFormat object itself and the "parent" property identifies the Format that has been overriden.
* This method is not intended for complete serialization as it does not serialize any of the schema item properties.
*/
getFormatProps() {
const formatJson = this.parent.toJSON();
if (this.parent.fullName !== this.fullName) {
// Update name and parent properties to distinguish it from parent Format
formatJson.name = this.fullName;
formatJson.parent = this.parent.fullName;
}
// Update Precision overriden property
formatJson.precision = this.precision;
if (this.units !== undefined) {
// Update Units overriden property
const units = [];
for (const unit of this.units) {
units.push({
name: unit[0].fullName,
label: unit[1],
});
}
formatJson.composite = {
spacer: (this.spacer !== " ") ? this.spacer : undefined,
includeZero: (this.includeZero === false) ? this.includeZero : undefined,
units,
};
}
return formatJson;
}
}
exports.OverrideFormat = OverrideFormat;
/**
* @internal
*/
function getFormatProps(format) {
return OverrideFormat.isOverrideFormat(format) ? format.getFormatProps() : format.toJSON();
}
//# sourceMappingURL=OverrideFormat.js.map