UNPKG

@itwin/presentation-common

Version:

Common pieces for iModel.js presentation packages

159 lines 7.17 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Core */ import { assert } from "@itwin/core-bentley"; import { Format, FormatterSpec, ParserSpec } from "@itwin/core-quantity"; import { InvertedUnit, KindOfQuantity, SchemaContext, SchemaFormatsProvider, SchemaKey, SchemaMatchType, SchemaUnitProvider } from "@itwin/ecschema-metadata"; /** * An utility for formatting property values based on `KindOfQuantity` and unit system. * @public */ export class KoqPropertyValueFormatter { _schemaContext; _unitsProvider; _formatsProvider; // eslint-disable-next-line @typescript-eslint/no-deprecated _defaultFormats; // eslint-disable-next-line @typescript-eslint/no-deprecated constructor(schemaContextOrProps, defaultFormats, formatsProvider) { if (schemaContextOrProps instanceof SchemaContext) { this._schemaContext = schemaContextOrProps; this._formatsProvider = formatsProvider; this.defaultFormats = defaultFormats; } else { this._schemaContext = schemaContextOrProps.schemaContext; this._formatsProvider = schemaContextOrProps.formatsProvider; } this._unitsProvider = new SchemaUnitProvider(this._schemaContext); } /* c8 ignore start */ /** @internal */ // eslint-disable-next-line @typescript-eslint/no-deprecated get defaultFormats() { return this._defaultFormats; } // eslint-disable-next-line @typescript-eslint/no-deprecated set defaultFormats(value) { this._defaultFormats = value ? Object.entries(value).reduce((acc, [phenomenon, unitSystemFormats]) => ({ ...acc, [phenomenon.toUpperCase()]: unitSystemFormats }), {}) : undefined; } /* c8 ignore end */ async format(value, options) { const formatterSpec = await this.getFormatterSpec(options); if (!formatterSpec) { return undefined; } return formatterSpec.applyFormatting(value); } async getFormatterSpec(options) { const formattingProps = await this.#getFormattingProps(options); if (!formattingProps) { return undefined; } const { formatProps, persistenceUnitName } = formattingProps; const persistenceUnit = await this._unitsProvider.findUnitByName(persistenceUnitName); const format = await Format.createFromJSON("", this._unitsProvider, { ...formatProps, ...options.formatOverride }); return FormatterSpec.create("", format, this._unitsProvider, persistenceUnit); } async getParserSpec(options) { const formattingProps = await this.#getFormattingProps(options); if (!formattingProps) { return undefined; } const { formatProps, persistenceUnitName } = formattingProps; const persistenceUnit = await this._unitsProvider.findUnitByName(persistenceUnitName); const format = await Format.createFromJSON("", this._unitsProvider, { ...formatProps, ...options.formatOverride }); return ParserSpec.create(format, this._unitsProvider, persistenceUnit); } async #getFormattingProps(options) { const { koqName } = options; const koq = await getKoq(this._schemaContext, koqName); if (!koq) { return undefined; } const persistenceUnit = await koq.persistenceUnit; assert(!!persistenceUnit); // default to metric as it's the persistence unit system const unitSystem = options.unitSystem ?? "metric"; const formatsProvider = this._formatsProvider ?? new SchemaFormatsProvider(this._schemaContext, unitSystem); const formatProps = await formatsProvider.getFormat(koqName); // `SchemaFormatsProvider` will fall back to default presentation format, but we want to fall back // to default formats' map first, and only then to the default presentation format. All of this can // be removed with the removal of default formats map. if (this._defaultFormats && (!formatProps || (await getUnitSystemKey(this._unitsProvider, formatProps)) !== unitSystem)) { const defaultFormatProps = await getFormatPropsFromDefaultFormats({ schemaContext: this._schemaContext, formatsMap: this._defaultFormats, unitSystem, koqName, }); if (defaultFormatProps) { return { formatProps: defaultFormatProps, persistenceUnitName: persistenceUnit.fullName }; } } if (formatProps) { return { formatProps, persistenceUnitName: persistenceUnit.fullName }; } return undefined; } } async function getKoq(schemaLocater, fullName) { const [schemaName, propKoqName] = fullName.split(":"); const schema = await schemaLocater.getSchema(new SchemaKey(schemaName), SchemaMatchType.Latest); if (!schema) { return undefined; } return schema.getItem(propKoqName, KindOfQuantity); } async function getUnitSystemKey(unitsProvider, formatProps) { const unitName = formatProps.composite?.units[0].name; assert(!!unitName); const unit = await unitsProvider.findUnitByName(unitName); assert(!!unit); const [_, unitSystemName] = unit.system.split(/[\.:]/); switch (unitSystemName.toUpperCase()) { case "METRIC": return "metric"; case "IMPERIAL": return "imperial"; case "USCUSTOM": return "usCustomary"; case "USSURVEY": return "usSurvey"; /* c8 ignore next 2 */ default: return undefined; } } async function getFormatPropsFromDefaultFormats({ schemaContext, formatsMap, unitSystem, koqName, }) { const koq = await getKoq(schemaContext, koqName); /* c8 ignore next 3 */ if (!koq) { return undefined; } const persistenceUnit = await koq.persistenceUnit; /* c8 ignore next 3 */ if (!persistenceUnit) { return undefined; } const actualPersistenceUnit = persistenceUnit instanceof InvertedUnit ? /* c8 ignore next */ await persistenceUnit.invertsUnit : persistenceUnit; const phenomenon = await actualPersistenceUnit?.phenomenon; if (phenomenon && formatsMap[phenomenon.name.toUpperCase()]) { const defaultPhenomenonFormats = formatsMap[phenomenon.name.toUpperCase()]; for (const defaultUnitSystemFormat of Array.isArray(defaultPhenomenonFormats) ? /* c8 ignore next */ defaultPhenomenonFormats : [defaultPhenomenonFormats]) { if (defaultUnitSystemFormat.unitSystems.includes(unitSystem)) { return defaultUnitSystemFormat.format; } } } return undefined; } //# sourceMappingURL=KoqPropertyValueFormatter.js.map