@itwin/ecschema-metadata
Version:
ECObjects core concepts in typescript
174 lines • 7.82 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
*/
import { DelayedPromiseWithProps } from "../DelayedPromise";
import { XmlSerializationUtils } from "../Deserialization/XmlSerializationUtils";
import { SchemaItemType } from "../ECObjects";
import { ECSchemaError, ECSchemaStatus } from "../Exception";
import { Phenomenon } from "./Phenomenon";
import { SchemaItem } from "./SchemaItem";
import { UnitSystem } from "./UnitSystem";
/**
* An abstract class that adds the ability to define Units and everything that goes with them, within an ECSchema as a
* first-class concept is to allow the iModel to not be dependent on any hard-coded Units
* @public @preview
*/
export class Unit extends SchemaItem {
schemaItemType = Unit.schemaItemType;
/** @internal */
static get schemaItemType() { return SchemaItemType.Unit; }
_phenomenon;
_unitSystem;
_definition;
_numerator;
_denominator;
_offset;
/** @internal */
constructor(schema, name) {
super(schema, name);
this._definition = "";
}
get phenomenon() { return this._phenomenon; }
get unitSystem() { return this._unitSystem; }
get definition() { return this._definition; }
get numerator() { return this._numerator ?? 1.0; }
get offset() { return this._offset ?? 0.0; }
get denominator() { return this._denominator ?? 1.0; }
get hasNumerator() { return (this._numerator !== undefined); }
get hasOffset() { return (this._offset !== undefined); }
get hasDenominator() { return (this._denominator !== undefined); }
/**
* Returns true if a conversion can be calculated between the input units
* @alpha
*/
static async areCompatible(unitA, unitB) {
const unitAPhenomenon = await unitA.phenomenon;
const unitBPhenomenon = await unitB.phenomenon;
if (!unitAPhenomenon || !unitBPhenomenon || !unitAPhenomenon.key.matches(unitBPhenomenon.key))
return false;
return true;
}
/**
* Type guard to check if the SchemaItem is of type Unit.
* @param item The SchemaItem to check.
* @returns True if the item is a Unit, false otherwise.
*/
static isUnit(item) {
if (item && item.schemaItemType === SchemaItemType.Unit)
return true;
return false;
}
/**
* Save this Unit'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.phenomenon = this.phenomenon.fullName;
schemaJson.unitSystem = this.unitSystem.fullName;
schemaJson.definition = this.definition;
if (this.hasNumerator)
schemaJson.numerator = this.numerator;
if (this.hasDenominator)
schemaJson.denominator = this.denominator;
if (this.hasOffset)
schemaJson.offset = this.offset;
return schemaJson;
}
/** @internal */
async toXml(schemaXml) {
const itemElement = await super.toXml(schemaXml);
const phenomenon = await this.phenomenon;
if (undefined !== phenomenon) {
const phenomenonName = XmlSerializationUtils.createXmlTypedName(this.schema, phenomenon.schema, phenomenon.name);
itemElement.setAttribute("phenomenon", phenomenonName);
}
const unitSystem = await this.unitSystem;
if (undefined !== unitSystem) {
const unitSystemName = XmlSerializationUtils.createXmlTypedName(this.schema, unitSystem.schema, unitSystem.name);
itemElement.setAttribute("unitSystem", unitSystemName);
}
itemElement.setAttribute("definition", this.definition);
if (this.hasNumerator)
itemElement.setAttribute("numerator", this.numerator.toString());
if (this.hasDenominator)
itemElement.setAttribute("denominator", this.denominator.toString());
if (this.hasOffset)
itemElement.setAttribute("offset", this.offset.toString());
return itemElement;
}
fromJSONSync(unitProps) {
super.fromJSONSync(unitProps);
const phenomenonSchemaItemKey = this.schema.getSchemaItemKey(unitProps.phenomenon);
if (!phenomenonSchemaItemKey)
throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Unable to locate the phenomenon ${unitProps.phenomenon}.`);
this._phenomenon = new DelayedPromiseWithProps(phenomenonSchemaItemKey, async () => {
const phenom = await this.schema.lookupItem(phenomenonSchemaItemKey, Phenomenon);
if (undefined === phenom)
throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Unable to locate the phenomenon ${unitProps.phenomenon}.`);
return phenom;
});
const unitSystemSchemaItemKey = this.schema.getSchemaItemKey(unitProps.unitSystem);
if (!unitSystemSchemaItemKey)
throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Unable to locate the unitSystem ${unitProps.unitSystem}.`);
this._unitSystem = new DelayedPromiseWithProps(unitSystemSchemaItemKey, async () => {
const unitSystem = await this.schema.lookupItem(unitSystemSchemaItemKey, UnitSystem);
if (undefined === unitSystem)
throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `Unable to locate the unitSystem ${unitProps.unitSystem}.`);
return unitSystem;
});
if (this._definition !== "" && unitProps.definition.toLowerCase() !== this._definition.toLowerCase())
throw new ECSchemaError(ECSchemaStatus.InvalidECJson, `The Unit ${this.name} has an invalid 'definition' attribute.`);
else if (this._definition === "")
this._definition = unitProps.definition;
if (undefined !== unitProps.numerator) {
if (unitProps.numerator !== this._numerator)
this._numerator = unitProps.numerator;
}
if (undefined !== unitProps.denominator) {
if (unitProps.denominator !== this._denominator)
this._denominator = unitProps.denominator;
}
if (undefined !== unitProps.offset) {
if (unitProps.offset !== this._offset)
this._offset = unitProps.offset;
}
}
async fromJSON(unitProps) {
this.fromJSONSync(unitProps);
}
/** @internal */
async setPhenomenon(phenomenon) {
this._phenomenon = phenomenon;
}
/** @internal */
async setUnitSystem(unitSystem) {
this._unitSystem = unitSystem;
}
/** @internal */
async setDefinition(definition) {
this._definition = definition;
}
/**
* Type assertion to check if the SchemaItem is of type Unit.
* @param item The SchemaItem to check.
* @returns The item cast to Unit if it is a Unit, undefined otherwise.
* @internal
*/
static assertIsUnit(item) {
if (!this.isUnit(item))
throw new ECSchemaError(ECSchemaStatus.InvalidSchemaItemType, `Expected '${SchemaItemType.Unit}' (Unit)`);
}
}
/**
* @internal
* An abstract class used for schema editing.
*/
export class MutableUnit extends Unit {
}
//# sourceMappingURL=Unit.js.map