@itwin/ecschema-metadata
Version:
ECObjects core concepts in typescript
189 lines • 8.56 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* 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.SchemaFormatsProvider = void 0;
const Context_1 = require("./Context");
const SchemaKey_1 = require("./SchemaKey");
const SchemaItem_1 = require("./Metadata/SchemaItem");
const Format_1 = require("./Metadata/Format");
const core_bentley_1 = require("@itwin/core-bentley");
const KindOfQuantity_1 = require("./Metadata/KindOfQuantity");
const OverrideFormat_1 = require("./Metadata/OverrideFormat");
const loggerCategory = "SchemaFormatsProvider";
/**
* Provides default formats and kind of quantities from a given SchemaContext or SchemaLocater.
* @beta
*/
class SchemaFormatsProvider {
_context;
_unitSystem;
_formatsRetrieved = new Set();
onFormatsChanged = new core_bentley_1.BeEvent();
/**
*
* @param contextOrLocater The SchemaContext or a different ISchemaLocater implementation used to retrieve the schema. The SchemaContext
* class implements the ISchemaLocater interface. If the provided locater is not a SchemaContext instance a new SchemaContext will be
* created and the locater will be added.
* @param unitSystem Used to lookup a default format through a schema specific algorithm, when the format retrieved is associated with a KindOfQuantity.
*/
constructor(contextOrLocater, unitSystem) {
if (contextOrLocater instanceof Context_1.SchemaContext) {
this._context = contextOrLocater;
}
else {
this._context = new Context_1.SchemaContext();
this._context.addLocater(contextOrLocater);
}
this._unitSystem = unitSystem;
}
get context() { return this._context; }
get unitSystem() { return this._unitSystem; }
set unitSystem(unitSystem) {
this._unitSystem = unitSystem;
this.clear();
}
clear() {
const formatsChanged = Array.from(this._formatsRetrieved);
this._formatsRetrieved.clear();
this.onFormatsChanged.raiseEvent({ formatsChanged });
}
/** When using a presentation unit from a KindOfQuantity, the label and description should come from the KindOfQuantity */
convertToFormatDefinition(format, kindOfQuantity) {
// Destructure all properties except 'rest'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { name, label, description, $schema, schema, schemaVersion, schemaItemType,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
customAttributes, originalECSpecMajorVersion, originalECSpecMinorVersion, ...rest } = format;
return {
...rest,
name: kindOfQuantity.fullName,
label: kindOfQuantity.label ?? format.label,
description: kindOfQuantity.description ?? format.description,
};
}
async getKindOfQuantityFormatFromSchema(itemKey) {
let kindOfQuantity;
try {
kindOfQuantity = await this._context.getSchemaItem(itemKey, KindOfQuantity_1.KindOfQuantity);
}
catch {
core_bentley_1.Logger.logError(loggerCategory, `Failed to find KindOfQuantity ${itemKey.fullName}`);
return undefined;
}
if (!kindOfQuantity) {
return undefined;
}
// Find the first presentation format that matches the provided unit system.
const unitSystemMatchers = getUnitSystemGroupMatchers(this._unitSystem);
const presentationFormats = kindOfQuantity.presentationFormats;
for (const matcher of unitSystemMatchers) {
for (const lazyFormat of presentationFormats) {
const format = await lazyFormat;
const unit = await (format.units && format.units[0][0]);
if (!unit) {
continue;
}
const currentUnitSystem = await unit.unitSystem;
if (currentUnitSystem && matcher(currentUnitSystem)) {
this._formatsRetrieved.add(itemKey.fullName);
const props = (0, OverrideFormat_1.getFormatProps)(format);
return this.convertToFormatDefinition(props, kindOfQuantity);
}
}
}
// If no matching presentation format was found, use persistence unit format if it matches unit system.
const persistenceUnit = await kindOfQuantity.persistenceUnit;
const persistenceUnitSystem = await persistenceUnit?.unitSystem;
if (persistenceUnitSystem && unitSystemMatchers.some((matcher) => matcher(persistenceUnitSystem))) {
this._formatsRetrieved.add(itemKey.fullName);
const props = getPersistenceUnitFormatProps(persistenceUnit);
return this.convertToFormatDefinition(props, kindOfQuantity);
}
const defaultFormat = kindOfQuantity.defaultPresentationFormat;
if (!defaultFormat) {
return undefined;
}
this._formatsRetrieved.add(itemKey.fullName);
const defaultProps = (0, OverrideFormat_1.getFormatProps)(await defaultFormat);
return this.convertToFormatDefinition(defaultProps, kindOfQuantity);
}
/**
* Retrieves a Format from a SchemaContext. If the format is part of a KindOfQuantity, the first presentation format in the KindOfQuantity that matches the current unit system will be retrieved.
* If no presentation format matches the current unit system, the persistence unit format will be retrieved if it matches the current unit system.
* Else, the default presentation format will be retrieved.
* @param name The full name of the Format or KindOfQuantity.
* @returns
*/
async getFormat(name) {
const [schemaName, schemaItemName] = SchemaItem_1.SchemaItem.parseFullName(name);
const schemaKey = new SchemaKey_1.SchemaKey(schemaName);
let schema;
try {
schema = await this._context.getSchema(schemaKey);
}
catch {
core_bentley_1.Logger.logError(loggerCategory, `Failed to find schema ${schemaName}`);
return undefined;
}
if (!schema) {
return undefined;
}
const itemKey = new SchemaKey_1.SchemaItemKey(schemaItemName, schema.schemaKey);
if (schema.name === "Formats") {
let format;
try {
format = await this._context.getSchemaItem(itemKey, Format_1.Format);
}
catch {
core_bentley_1.Logger.logError(loggerCategory, `Failed to find Format ${itemKey.fullName}`);
return undefined;
}
if (!format) {
return undefined;
}
return format.toJSON(true);
}
return this.getKindOfQuantityFormatFromSchema(itemKey);
}
}
exports.SchemaFormatsProvider = SchemaFormatsProvider;
function getUnitSystemGroupMatchers(groupKey) {
function createMatcher(name) {
const names = Array.isArray(name) ? name : [name];
return (unitSystem) => names.some((n) => n === unitSystem.name.toUpperCase());
}
switch (groupKey) {
case "imperial":
return ["IMPERIAL", "USCUSTOM", "INTERNATIONAL", "FINANCE"].map(createMatcher);
case "metric":
return [["SI", "METRIC"], "INTERNATIONAL", "FINANCE"].map(createMatcher);
case "usCustomary":
return ["USCUSTOM", "INTERNATIONAL", "FINANCE"].map(createMatcher);
case "usSurvey":
return ["USSURVEY", "USCUSTOM", "INTERNATIONAL", "FINANCE"].map(createMatcher);
}
return [];
}
function getPersistenceUnitFormatProps(persistenceUnit) {
// Same as Format "DefaultRealU" in Formats ecschema
return {
formatTraits: ["keepSingleZero", "keepDecimalPoint", "showUnitLabel"],
precision: 6,
type: "Decimal",
composite: {
units: [
{
name: persistenceUnit.fullName,
label: persistenceUnit.label,
},
],
},
};
}
//# sourceMappingURL=SchemaFormatsProvider.js.map