Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constraint customattributes prop #7506

Merged
merged 9 commits into from
Jan 10, 2025
4 changes: 4 additions & 0 deletions common/api/ecschema-metadata.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,10 @@ export interface RelationshipConstraintProps {
// (undocumented)
readonly constraintClasses: string[];
// (undocumented)
readonly customAttributes?: Array<{
[value: string]: any;
}>;
// (undocumented)
readonly multiplicity: string;
// (undocumented)
readonly polymorphic: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/ecschema-metadata",
"comment": "",
"type": "none"
}
],
"packageName": "@itwin/ecschema-metadata"
}
1 change: 1 addition & 0 deletions core/ecschema-metadata/src/Deserialization/JsonProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export interface RelationshipConstraintProps {
readonly polymorphic: boolean;
readonly abstractConstraint?: string;
readonly constraintClasses: string[];
readonly customAttributes?: Array<{ [value: string]: any }>;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down Expand Up @@ -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",
}] },
});
}

Expand Down Expand Up @@ -159,4 +175,206 @@ describe("RelationshipConstraint", () => {
assert.isTrue(testConstraint.customAttributes!.get("TestSchema.TestCAClassB")!.ShowClasses);
});
});

describe("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<RelationshipClass>("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<RelationshipClass>("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<RelationshipClass>("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;
});
});

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<RelationshipClass>("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<RelationshipClass>("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 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], "TestCAClassB");
assert.strictEqual(customAttribute2.length, 1);
const attribute2 = getElementChildrenByTagName(customAttribute2[0], "ShowClasses");
assert.strictEqual(attribute2.length, 1);
expect(attribute2[0].textContent).to.eql("True");
});
});
});
Loading