UNPKG

@itwin/ecschema-metadata

Version:

ECObjects core concepts in typescript

214 lines • 11.7 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 Metadata */ import { DelayedPromiseWithProps } from "../DelayedPromise"; import { XmlSerializationUtils } from "../Deserialization/XmlSerializationUtils"; import { SchemaItemType } from "../ECObjects"; import { ECSchemaError, ECSchemaStatus } from "../Exception"; import { Format } from "./Format"; import { InvertedUnit } from "./InvertedUnit"; import { OverrideFormat } from "./OverrideFormat"; import { SchemaItem } from "./SchemaItem"; import { Unit } from "./Unit"; /** A Typescript class representation of a KindOfQuantity. * @public @preview */ export class KindOfQuantity extends SchemaItem { schemaItemType = KindOfQuantity.schemaItemType; /** @internal */ static get schemaItemType() { return SchemaItemType.KindOfQuantity; } _relativeError = 1.0; _presentationFormats = []; _persistenceUnit; /** The first presentation format in the list of Formats. */ get defaultPresentationFormat() { return this.presentationFormats[0]; } /** A list of presentation formats. */ get presentationFormats() { return this._presentationFormats; } /** Persistence unit */ get persistenceUnit() { return this._persistenceUnit; } get relativeError() { return this._relativeError; } /** * * @param format The Format to add to this KindOfQuantity * @param isDefault * @internal */ addPresentationFormat(format, isDefault = false) { // TODO: Add some sort of validation? // eslint-disable-next-line @typescript-eslint/no-floating-promises (isDefault) ? this._presentationFormats.splice(0, 0, format) : this._presentationFormats.push(format); } /** Creates an OverrideFormat in the context of this KindOfQuantity. * @param parent The Format to override. * @param precision The precision override * @param unitLabelOverrides The list of unit and label overrides. * @internal */ createFormatOverride(parent, precision, unitLabelOverrides) { if (unitLabelOverrides && parent.units && parent.units.length !== unitLabelOverrides.length) throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Cannot add presentation format to KindOfQuantity '${this.name}' because the number of unit overrides is inconsistent with the number in the Format '${parent.name}'.`); if (parent.units && 0 === parent.units.length && unitLabelOverrides && 0 < unitLabelOverrides.length) throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Cannot add a presentation format to KindOfQuantity '${this.name}' without any units and no unit overrides.`); // TODO: Check compatibility of Unit overrides with the persistence unit return new OverrideFormat(parent, precision, unitLabelOverrides); } async processPresentationUnits(presentationUnitsJson) { const presUnitsArr = Array.isArray(presentationUnitsJson) ? presentationUnitsJson : presentationUnitsJson.split(";"); for (const formatString of presUnitsArr) { const presFormatOverride = OverrideFormat.parseFormatString(formatString); const format = await this.schema.lookupItem(presFormatOverride.name, Format); if (undefined === format || format.schemaItemType !== SchemaItemType.Format) throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Unable to locate Format '${presFormatOverride.name}' for the presentation unit on KindOfQuantity ${this.fullName}.`); if (undefined === presFormatOverride.precision && undefined === presFormatOverride.unitAndLabels) { this.addPresentationFormat(new DelayedPromiseWithProps(format.key, async () => format)); continue; } let unitAndLabels; if (undefined !== presFormatOverride.unitAndLabels) { if (4 < presFormatOverride.unitAndLabels.length) throw new ECSchemaError(ECSchemaStatus.InvalidECJson, ``); unitAndLabels = []; for (const unitOverride of presFormatOverride.unitAndLabels) { const unitOrInverted = await this.schema.lookupItem(unitOverride[0]); if (Unit.isUnit(unitOrInverted)) unitAndLabels.push([new DelayedPromiseWithProps(unitOrInverted.key, async () => unitOrInverted), unitOverride[1]]); else if (InvertedUnit.isInvertedUnit(unitOrInverted)) unitAndLabels.push([new DelayedPromiseWithProps(unitOrInverted.key, async () => unitOrInverted), unitOverride[1]]); else throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Unable to locate SchemaItem ${unitOverride[0]}.`); } } const overrideFormat = this.createFormatOverride(format, presFormatOverride.precision, unitAndLabels); this.addPresentationFormat(overrideFormat); } } processPresentationUnitsSync(presentationUnitsJson) { const presUnitsArr = Array.isArray(presentationUnitsJson) ? presentationUnitsJson : presentationUnitsJson.split(";"); for (const formatString of presUnitsArr) { const presFormatOverride = OverrideFormat.parseFormatString(formatString); const format = this.schema.lookupItemSync(presFormatOverride.name, Format); if (undefined === format || format.schemaItemType !== SchemaItemType.Format) throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Unable to locate Format '${presFormatOverride.name}' for the presentation unit on KindOfQuantity ${this.fullName}.`); if (undefined === presFormatOverride.precision && undefined === presFormatOverride.unitAndLabels) { this.addPresentationFormat(new DelayedPromiseWithProps(format.key, async () => format)); continue; } let unitAndLabels; if (undefined !== presFormatOverride.unitAndLabels) { if (4 < presFormatOverride.unitAndLabels.length) throw new ECSchemaError(ECSchemaStatus.InvalidECJson, ``); unitAndLabels = []; for (const unitOverride of presFormatOverride.unitAndLabels) { const unitOrInverted = this.schema.lookupItemSync(unitOverride[0]); if (Unit.isUnit(unitOrInverted)) unitAndLabels.push([new DelayedPromiseWithProps(unitOrInverted.key, async () => unitOrInverted), unitOverride[1]]); else if (InvertedUnit.isInvertedUnit(unitOrInverted)) unitAndLabels.push([new DelayedPromiseWithProps(unitOrInverted.key, async () => unitOrInverted), unitOverride[1]]); else throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Unable to locate SchemaItem ${unitOverride[0]}.`); } } const overrideFormat = this.createFormatOverride(format, presFormatOverride.precision, unitAndLabels); this.addPresentationFormat(overrideFormat); } } /** * Save this KindOfQuantity's properties to an object for serializing to JSON. * @param standalone Serialization includes only this object (as opposed to the full schema). * @param includeSchemaVersion Include the Schema's version information in the serialized object. */ toJSON(standalone = false, includeSchemaVersion = false) { const schemaJson = super.toJSON(standalone, includeSchemaVersion); schemaJson.relativeError = this.relativeError; schemaJson.persistenceUnit = this.persistenceUnit.fullName; if (undefined !== this.presentationFormats && 0 < this.presentationFormats.length) schemaJson.presentationUnits = this.presentationFormats.map((format) => format.fullName); return schemaJson; } /** @internal */ async toXml(schemaXml) { const itemElement = await super.toXml(schemaXml); const persistenceUnit = await this.persistenceUnit; if (undefined !== persistenceUnit) { const unitName = XmlSerializationUtils.createXmlTypedName(this.schema, persistenceUnit.schema, persistenceUnit.name); itemElement.setAttribute("persistenceUnit", unitName); } if (undefined !== this.presentationFormats) { const presUnitStrings = []; for (const format of this.presentationFormats) { if (!OverrideFormat.isOverrideFormat(format)) { const resolvedFormat = await format; presUnitStrings.push(XmlSerializationUtils.createXmlTypedName(this.schema, resolvedFormat.schema, format.name)); continue; } presUnitStrings.push(format.fullNameXml(this.schema)); } ; itemElement.setAttribute("presentationUnits", presUnitStrings.join(";")); } itemElement.setAttribute("relativeError", this.relativeError.toString()); return itemElement; } fromJSONSync(kindOfQuantityProps) { super.fromJSONSync(kindOfQuantityProps); this._relativeError = kindOfQuantityProps.relativeError; const unitItemKey = this.schema.getSchemaItemKey(kindOfQuantityProps.persistenceUnit); this._persistenceUnit = new DelayedPromiseWithProps(unitItemKey, async () => { const unitItem = await this.schema.lookupItem(unitItemKey, Unit) || await this.schema.lookupItem(unitItemKey, InvertedUnit); if (undefined === unitItem) throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Unable to locate the unit ${kindOfQuantityProps.persistenceUnit}.`); return unitItem; }); if (undefined !== kindOfQuantityProps.presentationUnits) this.processPresentationUnitsSync(kindOfQuantityProps.presentationUnits); } async fromJSON(kindOfQuantityProps) { this.fromJSONSync(kindOfQuantityProps); } /** * Used for schema editing. * @internal */ setRelativeError(relativeError) { this._relativeError = relativeError; } /** * Used for schema editing. * @internal */ setPersistenceUnit(value) { this._persistenceUnit = value; } /** * Type guard to check if the SchemaItem is of type KindOfQuantity. * @param item The SchemaItem to check. * @returns True if the item is a KindOfQuantity, false otherwise. */ static isKindOfQuantity(item) { if (item && item.schemaItemType === SchemaItemType.KindOfQuantity) return true; return false; } /** * Type assertion to check if the SchemaItem is of type KindOfQuantity. * @param item The SchemaItem to check. * @returns The item cast to KindOfQuantity if it is a KindOfQuantity, undefined otherwise. * @internal */ static assertIsKindOfQuantity(item) { if (!this.isKindOfQuantity(item)) throw new ECSchemaError(ECSchemaStatus.InvalidSchemaItemType, `Expected '${SchemaItemType.KindOfQuantity}' (KindOfQuantity)`); } } /** * @internal * An abstract class used for schema editing. */ export class MutableKindOfQuantity extends KindOfQuantity { } //# sourceMappingURL=KindOfQuantity.js.map