Skip to content

Commit

Permalink
Add addCustomAttribute to EC Class and Property method to editing API (
Browse files Browse the repository at this point in the history
…#3744)

* Add ability to add CA to Property in editing API

* wip

* change log

* remove it.only

* PR review updates

* PR updates

* fix lint errors
  • Loading branch information
christophermlawson authored Jun 9, 2022
1 parent 3442b93 commit 3edb603
Show file tree
Hide file tree
Showing 3 changed files with 382 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/ecschema-editing",
"comment": "Added support for adding CustomAttributes to EC Classes and Properties.",
"type": "none"
}
],
"packageName": "@itwin/ecschema-editing"
}
111 changes: 93 additions & 18 deletions core/ecschema-editing/src/Editing/ECClasses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@
*/

import {
CustomAttribute,
CustomAttributeContainerProps,
ECClass, ECObjectsError, ECObjectsStatus, Enumeration, EnumerationPropertyProps, PrimitiveArrayPropertyProps,
PrimitivePropertyProps, PrimitiveType, SchemaItemKey, SchemaItemType, StructArrayPropertyProps,
StructClass, StructPropertyProps,
} from "@itwin/ecschema-metadata";
import { assert } from "@itwin/core-bentley";
import { PropertyEditResults, SchemaContextEditor, SchemaItemEditResults } from "./Editor";
import { MutableClass } from "./Mutable/MutableClass";
import * as Rules from "../Validation/ECRules";
import { MutableProperty } from "./Mutable/MutableProperty";

/**
* @alpha
* Acts as a base class for schema class creation. Enables property creation.
*/
export class ECClasses {

protected constructor(protected _schemaEditor: SchemaContextEditor) { }

/**
Expand All @@ -41,7 +47,7 @@ export class ECClasses {
const prefixedName = `${prefix}_${name}`;

try {
mutableClass = await this.getClass(classKey, prefixedName);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -59,7 +65,7 @@ export class ECClasses {
public async createPrimitiveProperty(classKey: SchemaItemKey, name: string, type: PrimitiveType): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -71,7 +77,7 @@ export class ECClasses {
public async createPrimitivePropertyFromProps(classKey: SchemaItemKey, name: string, type: PrimitiveType, primitiveProps: PrimitivePropertyProps): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -84,7 +90,7 @@ export class ECClasses {
public async createEnumerationProperty(classKey: SchemaItemKey, name: string, type: Enumeration): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -98,7 +104,7 @@ export class ECClasses {
public async createEnumerationPropertyFromProps(classKey: SchemaItemKey, name: string, type: Enumeration, enumProps: EnumerationPropertyProps): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -110,7 +116,7 @@ export class ECClasses {
public async createPrimitiveArrayProperty(classKey: SchemaItemKey, name: string, type: PrimitiveType): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -122,7 +128,7 @@ export class ECClasses {
public async createPrimitiveArrayPropertyFromProps(classKey: SchemaItemKey, name: string, type: PrimitiveType, primitiveProps: PrimitiveArrayPropertyProps): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -135,7 +141,7 @@ export class ECClasses {
public async createStructProperty(classKey: SchemaItemKey, name: string, type: StructClass): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -147,7 +153,7 @@ export class ECClasses {
public async createStructPropertyFromProps(classKey: SchemaItemKey, name: string, type: StructClass, structProps: StructPropertyProps): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -160,7 +166,7 @@ export class ECClasses {
public async createStructArrayProperty(classKey: SchemaItemKey, name: string, type: StructClass): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -172,7 +178,7 @@ export class ECClasses {
public async createStructArrayPropertyFromProps(classKey: SchemaItemKey, name: string, type: StructClass, structProps: StructArrayPropertyProps): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -185,7 +191,7 @@ export class ECClasses {
public async deleteProperty(classKey: SchemaItemKey, name: string): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey, name);
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}
Expand All @@ -208,14 +214,77 @@ export class ECClasses {
return { itemKey: classKey };
}

private async getClass(classKey: SchemaItemKey, name: string): Promise<MutableClass> {
const schema = await this._schemaEditor.getSchema(classKey.schemaKey);
if (schema === undefined)
throw new Error(`Failed to create property ${name} because the schema ${classKey.schemaKey.toString(true)} could not be found`);
/**
* Adds a CustomAttribute instance to the Class identified by the given SchemaItemKey
* @param classKey The SchemaItemKey identifying the schema.
* @param customAttribute The CustomAttribute instance to add.
*/
public async addCustomAttribute(classKey: SchemaItemKey, customAttribute: CustomAttribute): Promise<SchemaItemEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}

mutableClass.addCustomAttribute(customAttribute);

const diagnostics = Rules.validateCustomAttributeInstance(mutableClass, customAttribute);

const result: SchemaItemEditResults = { errorMessage: "" };
for await (const diagnostic of diagnostics) {
result.errorMessage += `${diagnostic.code}: ${diagnostic.messageText}\r\n`;
}

if (result.errorMessage) {
this.removeCustomAttribute(mutableClass, customAttribute);
return result;
}

return {};
}

/**
* Adds a CustomAttribute instance to the Property identified by the given SchemaItemKey and property name.
* @param classKey The SchemaItemKey identifying the class.
* @param propertyName The name of the property.
* @param customAttribute The CustomAttribute instance to add.
*/
public async addCustomAttributeToProperty(classKey: SchemaItemKey, propertyName: string, customAttribute: CustomAttribute): Promise<PropertyEditResults> {
let mutableClass: MutableClass;
try {
mutableClass = await this.getClass(classKey);
} catch (e: any) {
return { errorMessage: e.message };
}

const property = await mutableClass.getProperty(propertyName) as MutableProperty;
if (!property) {
return { errorMessage: `Property with the name ${propertyName} could not be found in the class ${classKey.fullName}.` };
}

property.addCustomAttribute(customAttribute);

const diagnostics = Rules.validateCustomAttributeInstance(property, customAttribute);

const result: SchemaItemEditResults = { errorMessage: "" };
for await (const diagnostic of diagnostics) {
result.errorMessage += `${diagnostic.code}: ${diagnostic.messageText}\r\n`;
}

if (result.errorMessage) {
this.removeCustomAttribute(property, customAttribute);
return result;
}

return {};
}

private async getClass(classKey: SchemaItemKey): Promise<MutableClass> {
const schema = await this._schemaEditor.getSchema(classKey.schemaKey);
const ecClass = await schema.getItem<MutableClass>(classKey.name);
if (ecClass === undefined)
throw new Error(`Failed to create property ${name} because the class ${classKey.name} was not found in ${classKey.schemaKey.toString(true)}`);
throw new ECObjectsError(ECObjectsStatus.ClassNotFound, `Class ${classKey.name} was not found in schema ${classKey.schemaKey.toString(true)}`);

switch (ecClass.schemaItemType) {
case SchemaItemType.EntityClass:
Expand All @@ -225,10 +294,16 @@ export class ECClasses {
case SchemaItemType.RelationshipClass:
break;
default:
throw new Error(`Schema item type not supported`);
throw new ECObjectsError(ECObjectsStatus.InvalidSchemaItemType, `Schema item type not supported`);
}

return ecClass;
}

private removeCustomAttribute(container: CustomAttributeContainerProps, customAttribute: CustomAttribute) {
assert(container.customAttributes !== undefined);
const map = container.customAttributes as Map<string, CustomAttribute>;
map.delete(customAttribute.className);
}
}

Loading

0 comments on commit 3edb603

Please sign in to comment.