From 08362ef98948f1622363a3df8d8481f901b441c3 Mon Sep 17 00:00:00 2001 From: christophermlawson <32881725+christophermlawson@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:46:39 -0500 Subject: [PATCH 1/5] Add customAttribute prop to RelationshipConstraintProps interface --- .../src/Deserialization/JsonProps.ts | 1 + .../Metadata/RelationshipConstraint.test.ts | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/core/ecschema-metadata/src/Deserialization/JsonProps.ts b/core/ecschema-metadata/src/Deserialization/JsonProps.ts index 2e4404ba7796..c003764a3a81 100644 --- a/core/ecschema-metadata/src/Deserialization/JsonProps.ts +++ b/core/ecschema-metadata/src/Deserialization/JsonProps.ts @@ -136,6 +136,7 @@ export interface RelationshipConstraintProps { readonly polymorphic: boolean; readonly abstractConstraint?: string; readonly constraintClasses: string[]; + readonly customAttributes?: Array<{ [value: string]: any }>; } /** diff --git a/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts b/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts index d2399c46e2fd..35b066f6563c 100644 --- a/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts @@ -159,4 +159,101 @@ describe("RelationshipConstraint", () => { assert.isTrue(testConstraint.customAttributes!.get("TestSchema.TestCAClassB")!.ShowClasses); }); }); + + describe.only("toJson", () => { + let testConstraint: RelationshipConstraint; + + beforeEach(() => { + const schema = new Schema(new SchemaContext(), "TestSchema", "ts", 1, 0, 0); + const relClass = new RelationshipClass(schema, "TestRelationship"); + testConstraint = new RelationshipConstraint(relClass, RelationshipEnd.Source); + }); + + const targetStubJson = { + polymorphic: false, + multiplicity: "(0..*)", + roleLabel: "Test Target roleLabel", + constraintClasses: [ + "TestSchema.TestTargetEntity", + ], + }; + + const oneCustomAttributeJson = { + polymorphic: true, + multiplicity: "(0..1)", + roleLabel: "Test Source roleLabel", + constraintClasses: [ + "TestSchema.TestSourceEntity", + ], + customAttributes: [ + { + className: "TestSchema.TestCAClassA", + ShowClasses: true, + }, + ], + }; + + it("Serialize One Custom Attribute", async () => { + const schema = await Schema.fromJson(createSchemaJson(oneCustomAttributeJson, targetStubJson), new SchemaContext()); + testConstraint = (await schema.getItem("TestRelationship"))!.source; + expect(testConstraint).to.exist; + const constraintProps = testConstraint.toJSON(); + assert.isTrue(constraintProps.customAttributes![0].ShowClasses); + }); + + const twoCustomAttributesJson = { + $schema: "https://dev.bentley.com/json_schemas/ec/32/ecschema", + name: "ValidSchema", + polymorphic: true, + multiplicity: "(0..1)", + roleLabel: "Test Source roleLabel", + constraintClasses: [ + "TestSchema.TestTargetEntity", + ], + customAttributes: [ + { + className: "TestSchema.TestCAClassA", + }, + { + className: "TestSchema.TestCAClassB", + }, + ], + }; + + it("Serialize Two Custom Attributes", async () => { + const schema = await Schema.fromJson(createSchemaJson(twoCustomAttributesJson, targetStubJson), new SchemaContext()); + testConstraint = (await schema.getItem("TestRelationship"))!.source; + expect(testConstraint).to.exist; + const constraintProps = testConstraint.toJSON(); + expect(constraintProps.customAttributes![0].className).to.equal("TestSchema.TestCAClassA"); + expect(constraintProps.customAttributes![1].className).to.equal("TestSchema.TestCAClassB"); + }); + + it("Serialize Two Custom Attributes with additional properties", () => { + const relConstraintJson = { + polymorphic: true, + multiplicity: "(0..1)", + roleLabel: "test roleLabel", + constraintClasses: [ + "TestSchema.TestTargetEntity", + ], + customAttributes: [ + { + className: "TestSchema.TestCAClassA", + ShowClasses: false, + }, + { + className: "TestSchema.TestCAClassB", + ShowClasses: true, + }, + ], + }; + const schema = Schema.fromJsonSync(createSchemaJson(relConstraintJson, targetStubJson), new SchemaContext()); + testConstraint = schema.getItemSync("TestRelationship")!.source; + expect(testConstraint).to.exist; + const constraintProps = testConstraint.toJSON(); + expect(constraintProps.customAttributes![0].ShowClasses).to.be.false; + expect(constraintProps.customAttributes![1].ShowClasses).to.be.true; + }); + }); }); From 368370873f79c2f1173b7b654127e2bd49ee1f01 Mon Sep 17 00:00:00 2001 From: christophermlawson <32881725+christophermlawson@users.noreply.github.com> Date: Fri, 20 Dec 2024 08:50:10 -0500 Subject: [PATCH 2/5] further tests --- .../Metadata/RelationshipConstraint.test.ts | 129 +++++++++++++++++- 1 file changed, 125 insertions(+), 4 deletions(-) diff --git a/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts b/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts index 35b066f6563c..7938f6f9cfab 100644 --- a/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts @@ -9,6 +9,7 @@ import { ECObjectsError } from "../../Exception"; import { RelationshipClass, RelationshipConstraint } from "../../Metadata/RelationshipClass"; import { Schema } from "../../Metadata/Schema"; import { createSchemaJsonWithItems } from "../TestUtils/DeserializationHelpers"; +import { createEmptyXmlDocument, getElementChildren, getElementChildrenByTagName } from "../TestUtils/SerializationHelper"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -39,9 +40,24 @@ function createSchemaJson(sourceConst: any, targetConst: any) { schemaItemType: "EntityClass", baseClass: "TestSchema.TargetBaseEntity", }, - TestCAClassA: { schemaItemType: "CustomAttributeClass", appliesTo: "Any" }, - TestCAClassB: { schemaItemType: "CustomAttributeClass", appliesTo: "Any" }, - TestCAClassC: { schemaItemType: "CustomAttributeClass", appliesTo: "Any" }, + TestCAClassA: { schemaItemType: "CustomAttributeClass", appliesTo: "Any", properties: [ + { + name: "ShowClasses", + type: "PrimitiveProperty", + typeName: "boolean", + }]}, + TestCAClassB: { schemaItemType: "CustomAttributeClass", appliesTo: "Any", properties: [ + { + name: "ShowClasses", + type: "PrimitiveProperty", + typeName: "boolean", + }]}, + TestCAClassC: { schemaItemType: "CustomAttributeClass", appliesTo: "Any", properties: [ + { + name: "ShowClasses", + type: "PrimitiveProperty", + typeName: "boolean", + }] }, }); } @@ -160,7 +176,7 @@ describe("RelationshipConstraint", () => { }); }); - describe.only("toJson", () => { + describe("toJson", () => { let testConstraint: RelationshipConstraint; beforeEach(() => { @@ -256,4 +272,109 @@ describe("RelationshipConstraint", () => { expect(constraintProps.customAttributes![1].ShowClasses).to.be.true; }); }); + + describe("toXML", () => { + const newDom = createEmptyXmlDocument(); + let testConstraint: RelationshipConstraint; + + beforeEach(() => { + const schema = new Schema(new SchemaContext(), "TestSchema", "ts", 1, 0, 0); + const relClass = new RelationshipClass(schema, "TestRelationship"); + testConstraint = new RelationshipConstraint(relClass, RelationshipEnd.Source); + }); + + const targetStubJson = { + polymorphic: false, + multiplicity: "(0..*)", + roleLabel: "Test Target roleLabel", + constraintClasses: [ + "TestSchema.TestTargetEntity", + ], + }; + + const oneCustomAttributeJson = { + polymorphic: true, + multiplicity: "(0..1)", + roleLabel: "Test Source roleLabel", + constraintClasses: [ + "TestSchema.TestSourceEntity", + ], + customAttributes: [ + { + className: "TestSchema.TestCAClassA", + ShowClasses: true, + }, + ], + }; + + it("Serialize One Custom Attribute", async () => { + const schema = await Schema.fromJson(createSchemaJson(oneCustomAttributeJson, targetStubJson), new SchemaContext()); + testConstraint = (await schema.getItem("TestRelationship"))!.source; + expect(testConstraint).to.exist; + const serialized = await testConstraint.toXml(newDom); + expect(serialized.nodeName).to.eql("Source"); + expect(serialized.getAttribute("polymorphic")).to.eql("true"); + expect(serialized.getAttribute("multiplicity")).to.eql("(0..1)"); + expect(serialized.getAttribute("roleLabel")).to.eql("Test Source roleLabel"); + const children = getElementChildren(serialized); + assert.strictEqual(children.length, 2); + + const customAttributes = getElementChildrenByTagName(serialized, "ECCustomAttributes"); + assert.strictEqual(customAttributes.length, 1); + const customAttribute = getElementChildrenByTagName(customAttributes[0], "TestCAClassA"); + assert.strictEqual(customAttribute.length, 1); + const attribute = getElementChildrenByTagName(customAttribute[0], "ShowClasses"); + assert.strictEqual(attribute.length, 1); + expect(attribute[0].textContent).to.eql("True"); + }); + + const twoCustomAttributesJson = { + $schema: "https://dev.bentley.com/json_schemas/ec/32/ecschema", + name: "ValidSchema", + polymorphic: true, + multiplicity: "(0..1)", + roleLabel: "Test Source roleLabel", + constraintClasses: [ + "TestSchema.TestTargetEntity", + ], + customAttributes: [ + { + className: "TestSchema.TestCAClassA", + ShowClasses: true, + }, + { + className: "TestSchema.TestCAClassB", + ShowClasses: true, + }, + ], + }; + + it("Serialize Two Custom Attributes", async () => { + const schema = await Schema.fromJson(createSchemaJson(twoCustomAttributesJson, targetStubJson), new SchemaContext()); + testConstraint = (await schema.getItem("TestRelationship"))!.source; + expect(testConstraint).to.exist; + const serialized = await testConstraint.toXml(newDom); + + expect(serialized.nodeName).to.eql("Source"); + expect(serialized.getAttribute("polymorphic")).to.eql("true"); + expect(serialized.getAttribute("multiplicity")).to.eql("(0..1)"); + expect(serialized.getAttribute("roleLabel")).to.eql("Test Source roleLabel"); + const children = getElementChildren(serialized); + assert.strictEqual(children.length, 2); + + const customAttributes = getElementChildrenByTagName(serialized, "ECCustomAttributes"); + assert.strictEqual(customAttributes.length, 2); + const customAttribute1 = getElementChildrenByTagName(customAttributes[0], "TestCAClassA"); + assert.strictEqual(customAttribute1.length, 1); + const attribute1 = getElementChildrenByTagName(customAttribute1[0], "ShowClasses"); + assert.strictEqual(attribute1.length, 1); + expect(attribute1[0].textContent).to.eql("True"); + + const customAttribute2 = getElementChildrenByTagName(customAttributes[0], "TestCAClassA"); + assert.strictEqual(customAttribute2.length, 1); + const attribute2 = getElementChildrenByTagName(customAttribute2[0], "ShowClasses"); + assert.strictEqual(attribute2.length, 1); + expect(attribute2[0].textContent).to.eql("True"); + }); + }); }); From f562c802c13c42da44a4137fa63bc2e25c784631 Mon Sep 17 00:00:00 2001 From: christophermlawson <32881725+christophermlawson@users.noreply.github.com> Date: Fri, 20 Dec 2024 10:16:47 -0500 Subject: [PATCH 3/5] rush extract-api --- common/api/ecschema-metadata.api.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/api/ecschema-metadata.api.md b/common/api/ecschema-metadata.api.md index 65aa6b2cd239..05116023e5db 100644 --- a/common/api/ecschema-metadata.api.md +++ b/common/api/ecschema-metadata.api.md @@ -1529,6 +1529,10 @@ export interface RelationshipConstraintProps { // (undocumented) readonly constraintClasses: string[]; // (undocumented) + readonly customAttributes?: Array<{ + [value: string]: any; + }>; + // (undocumented) readonly multiplicity: string; // (undocumented) readonly polymorphic: boolean; From 9e923dc255e625dee87102b726a43c1a58adc165 Mon Sep 17 00:00:00 2001 From: christophermlawson <32881725+christophermlawson@users.noreply.github.com> Date: Fri, 20 Dec 2024 10:40:01 -0500 Subject: [PATCH 4/5] rush change --- ...straint-customattributes-prop_2024-12-20-15-39.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@itwin/ecschema-metadata/constraint-customattributes-prop_2024-12-20-15-39.json diff --git a/common/changes/@itwin/ecschema-metadata/constraint-customattributes-prop_2024-12-20-15-39.json b/common/changes/@itwin/ecschema-metadata/constraint-customattributes-prop_2024-12-20-15-39.json new file mode 100644 index 000000000000..5dd8c0e532c0 --- /dev/null +++ b/common/changes/@itwin/ecschema-metadata/constraint-customattributes-prop_2024-12-20-15-39.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/ecschema-metadata", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/ecschema-metadata" +} \ No newline at end of file From c49d429613be3277f404bf1e281c6bd5775812e8 Mon Sep 17 00:00:00 2001 From: christophermlawson <32881725+christophermlawson@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:25:15 -0500 Subject: [PATCH 5/5] test fix --- .../src/test/Metadata/RelationshipConstraint.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts b/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts index 7938f6f9cfab..daa4a5e076fb 100644 --- a/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/RelationshipConstraint.test.ts @@ -363,14 +363,14 @@ describe("RelationshipConstraint", () => { assert.strictEqual(children.length, 2); const customAttributes = getElementChildrenByTagName(serialized, "ECCustomAttributes"); - assert.strictEqual(customAttributes.length, 2); + assert.strictEqual(customAttributes.length, 1); const customAttribute1 = getElementChildrenByTagName(customAttributes[0], "TestCAClassA"); assert.strictEqual(customAttribute1.length, 1); const attribute1 = getElementChildrenByTagName(customAttribute1[0], "ShowClasses"); assert.strictEqual(attribute1.length, 1); expect(attribute1[0].textContent).to.eql("True"); - const customAttribute2 = getElementChildrenByTagName(customAttributes[0], "TestCAClassA"); + const customAttribute2 = getElementChildrenByTagName(customAttributes[0], "TestCAClassB"); assert.strictEqual(customAttribute2.length, 1); const attribute2 = getElementChildrenByTagName(customAttribute2[0], "ShowClasses"); assert.strictEqual(attribute2.length, 1);