From 1f5d8ca460e387ab0c7fb6448437968c07e248df Mon Sep 17 00:00:00 2001 From: RohitPtnkr1996 <111407262+RohitPtnkr1996@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:56:51 +0530 Subject: [PATCH 1/4] ChannelRoot gets created with the correct aspect relationship class --- common/api/core-backend.api.md | 7 ++++ common/api/summary/core-backend.exports.csv | 1 + ...r-channelroot-aspect_2025-11-24-10-24.json | 10 ++++++ core/backend/src/NavigationRelationship.ts | 16 +++++++-- core/backend/src/internal/ChannelAdmin.ts | 10 +++++- .../src/test/element/ElementAspect.test.ts | 35 +++++++++++++++++++ 6 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 common/changes/@itwin/core-backend/rohitptnkr-use-correct-relclass-for-channelroot-aspect_2025-11-24-10-24.json diff --git a/common/api/core-backend.api.md b/common/api/core-backend.api.md index bf2ea7e59cdf..a44a890c12d2 100644 --- a/common/api/core-backend.api.md +++ b/common/api/core-backend.api.md @@ -2592,6 +2592,13 @@ export class ElementMultiAspect extends ElementAspect { static get className(): string; } +// @beta +export class ElementOwnsChannelRootAspect extends ElementOwnsUniqueAspect { + constructor(elementId: Id64String, relClassName?: string); + // (undocumented) + static classFullName: string; +} + // @public export class ElementOwnsChildElements extends RelatedElement { constructor(parentId: Id64String, relClassName?: string); diff --git a/common/api/summary/core-backend.exports.csv b/common/api/summary/core-backend.exports.csv index 1f49448fb98a..68672f491a1c 100644 --- a/common/api/summary/core-backend.exports.csv +++ b/common/api/summary/core-backend.exports.csv @@ -190,6 +190,7 @@ public;class;ElementGroupsMembers public;interface;ElementGroupsMembersProps public;class;ElementMultiAspect preview;class;ElementMultiAspect +beta;class;ElementOwnsChannelRootAspect public;class;ElementOwnsChildElements public;class;ElementOwnsExternalSourceAspects public;class;ElementOwnsMultiAspects diff --git a/common/changes/@itwin/core-backend/rohitptnkr-use-correct-relclass-for-channelroot-aspect_2025-11-24-10-24.json b/common/changes/@itwin/core-backend/rohitptnkr-use-correct-relclass-for-channelroot-aspect_2025-11-24-10-24.json new file mode 100644 index 000000000000..a73642acb544 --- /dev/null +++ b/common/changes/@itwin/core-backend/rohitptnkr-use-correct-relclass-for-channelroot-aspect_2025-11-24-10-24.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-backend", + "comment": "ChannelRootAspect gets created with the correct relationship class.", + "type": "none" + } + ], + "packageName": "@itwin/core-backend" +} \ No newline at end of file diff --git a/core/backend/src/NavigationRelationship.ts b/core/backend/src/NavigationRelationship.ts index fe0a3fbf1fe6..2123e984de2e 100644 --- a/core/backend/src/NavigationRelationship.ts +++ b/core/backend/src/NavigationRelationship.ts @@ -110,7 +110,7 @@ export class FolderContainsRepositories extends ElementOwnsChildElements { export class SheetIndexFolderOwnsEntries extends ElementOwnsChildElements { public static override classFullName = "BisCore:SheetIndexFolderOwnsEntries"; public constructor(parentId: Id64String, relClassName: string = SheetIndexFolderOwnsEntries.classFullName) { - super(parentId, relClassName ); + super(parentId, relClassName); } } @@ -120,7 +120,7 @@ export class SheetIndexFolderOwnsEntries extends ElementOwnsChildElements { export class SheetIndexOwnsEntries extends ElementOwnsChildElements { public static override classFullName = "BisCore:SheetIndexOwnsEntries"; public constructor(parentId: Id64String, relClassName: string = SheetIndexOwnsEntries.classFullName) { - super(parentId, relClassName ); + super(parentId, relClassName); } } @@ -287,3 +287,15 @@ export class SheetOwnsSheetInformationAspect extends ElementOwnsUniqueAspect { super(sheetId, relClassName); } } + +/** Relates an [[Element]] to the [[ChannelRootAspect]] that identifies it as a channel root. + * @see [[ChannelControl.makeChannelRoot]] to create an instance of this relationship. + * @beta + */ +export class ElementOwnsChannelRootAspect extends ElementOwnsUniqueAspect { + public static override classFullName = "BisCore:ElementOwnsChannelRootAspect"; + + public constructor(elementId: Id64String, relClassName = ElementOwnsChannelRootAspect.classFullName) { + super(elementId, relClassName); + } +} diff --git a/core/backend/src/internal/ChannelAdmin.ts b/core/backend/src/internal/ChannelAdmin.ts index 01fc0a2eace1..314de77c95b1 100644 --- a/core/backend/src/internal/ChannelAdmin.ts +++ b/core/backend/src/internal/ChannelAdmin.ts @@ -12,6 +12,7 @@ import { ChannelControl, ChannelKey } from "../ChannelControl"; import { Subject } from "../Element"; import { IModelDb } from "../IModelDb"; import { IModelHost } from "../IModelHost"; +import { ElementOwnsChannelRootAspect } from "../NavigationRelationship"; import { _implementationProhibited, _nativeDb, _verifyChannel } from "./Symbols"; class ChannelAdmin implements ChannelControl { @@ -94,7 +95,14 @@ class ChannelAdmin implements ChannelControl { if (this.queryChannelRoot(args.channelKey) !== undefined) ChannelControlError.throwError("root-exists", `Channel ${args.channelKey} root already exist`, channelKey); - const props: ChannelRootAspectProps = { classFullName: ChannelAdmin.channelClassName, element: { id: args.elementId }, owner: args.channelKey }; + const props: ChannelRootAspectProps = { + classFullName: ChannelAdmin.channelClassName, + element: { + id: args.elementId, + relClassName: ElementOwnsChannelRootAspect.classFullName, + }, + owner: args.channelKey, + }; this._iModel.elements.insertAspect(props); } diff --git a/core/backend/src/test/element/ElementAspect.test.ts b/core/backend/src/test/element/ElementAspect.test.ts index 54d64a5a3906..1c8c07368ea8 100644 --- a/core/backend/src/test/element/ElementAspect.test.ts +++ b/core/backend/src/test/element/ElementAspect.test.ts @@ -411,4 +411,39 @@ describe("ElementAspect", () => { assert.equal(ExternalSourceAspect.findAllBySource(iModelDb, scopeId1, kind, "").length, 0); }); + it("should create ChannelRootAspect with correct relationship class", async () => { + const iModelDb = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ElementAspect", "ChannelRootAspectTest.bim"), { rootSubject: { name: "ChannelRootAspectTest" } }); + + const testChannelKey = "test-channel"; + + // Enable the test channel + iModelDb.channels.addAllowedChannel(testChannelKey); + + // Create a channel subject using insertChannelSubject + const subjectId = iModelDb.channels.insertChannelSubject({ + subjectName: "Test Channel Subject", + channelKey: testChannelKey, + }); + iModelDb.saveChanges(); + assert.isTrue(Id64.isValidId64(subjectId), "Subject ID should be valid"); + + // Get the ChannelRootAspect + const aspects = iModelDb.elements.getAspects(subjectId, "BisCore:ChannelRootAspect"); + assert.equal(aspects.length, 1, "Should be exactly one as it's a unique aspect"); + + const aspect = aspects[0]; + assert.exists(aspect); + assert.equal(aspect.classFullName, "BisCore:ChannelRootAspect", "Aspect class should be ChannelRootAspect"); + + // Verify the relationship class + expect(aspect.element.relClassName).to.equal("BisCore.ElementOwnsChannelRootAspect"); + assert.equal((aspect as any).owner, testChannelKey, "Channel owner should match the channel key"); + + // Query the db to confirm the relationship class + const reader = iModelDb.createQueryReader("select ec_classname(Element.RelECClassId) as relClassName from BisCore.ChannelRootAspect"); + expect(await reader.step()).to.be.true; + expect(reader.current.relClassName).to.equal("BisCore:ElementOwnsChannelRootAspect"); + + iModelDb.close(); + }); }); From 9d04210b28baa57932614dabe92049b0642a419c Mon Sep 17 00:00:00 2001 From: RohitPtnkr1996 <111407262+RohitPtnkr1996@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:58:06 +0530 Subject: [PATCH 2/4] Changelog commit --- ...orrect-relclass-for-channelroot-aspect_2025-11-24-10-24.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/changes/@itwin/core-backend/rohitptnkr-use-correct-relclass-for-channelroot-aspect_2025-11-24-10-24.json b/common/changes/@itwin/core-backend/rohitptnkr-use-correct-relclass-for-channelroot-aspect_2025-11-24-10-24.json index a73642acb544..06f0e0d30615 100644 --- a/common/changes/@itwin/core-backend/rohitptnkr-use-correct-relclass-for-channelroot-aspect_2025-11-24-10-24.json +++ b/common/changes/@itwin/core-backend/rohitptnkr-use-correct-relclass-for-channelroot-aspect_2025-11-24-10-24.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-backend", - "comment": "ChannelRootAspect gets created with the correct relationship class.", + "comment": "ChannelRoot gets created with the correct aspect relationship class.", "type": "none" } ], From 3dfe69785c32dbedff6fe0dfaec9994dbf99104f Mon Sep 17 00:00:00 2001 From: RohitPtnkr1996 <111407262+RohitPtnkr1996@users.noreply.github.com> Date: Tue, 25 Nov 2025 19:26:56 +0530 Subject: [PATCH 3/4] Update core/backend/src/NavigationRelationship.ts Co-authored-by: Paul Connelly <22944042+pmconne@users.noreply.github.com> --- core/backend/src/NavigationRelationship.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/backend/src/NavigationRelationship.ts b/core/backend/src/NavigationRelationship.ts index 2123e984de2e..de5e887e624d 100644 --- a/core/backend/src/NavigationRelationship.ts +++ b/core/backend/src/NavigationRelationship.ts @@ -290,7 +290,7 @@ export class SheetOwnsSheetInformationAspect extends ElementOwnsUniqueAspect { /** Relates an [[Element]] to the [[ChannelRootAspect]] that identifies it as a channel root. * @see [[ChannelControl.makeChannelRoot]] to create an instance of this relationship. - * @beta + * @public */ export class ElementOwnsChannelRootAspect extends ElementOwnsUniqueAspect { public static override classFullName = "BisCore:ElementOwnsChannelRootAspect"; From 315b2133961a5897e9342c62545bb63cafe733f4 Mon Sep 17 00:00:00 2001 From: RohitPtnkr1996 <111407262+RohitPtnkr1996@users.noreply.github.com> Date: Tue, 25 Nov 2025 19:50:07 +0530 Subject: [PATCH 4/4] Updated api signatures --- common/api/core-backend.api.md | 2 +- common/api/summary/core-backend.exports.csv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/api/core-backend.api.md b/common/api/core-backend.api.md index a44a890c12d2..c005f4c721f3 100644 --- a/common/api/core-backend.api.md +++ b/common/api/core-backend.api.md @@ -2592,7 +2592,7 @@ export class ElementMultiAspect extends ElementAspect { static get className(): string; } -// @beta +// @public export class ElementOwnsChannelRootAspect extends ElementOwnsUniqueAspect { constructor(elementId: Id64String, relClassName?: string); // (undocumented) diff --git a/common/api/summary/core-backend.exports.csv b/common/api/summary/core-backend.exports.csv index 68672f491a1c..bd9c2cdb3494 100644 --- a/common/api/summary/core-backend.exports.csv +++ b/common/api/summary/core-backend.exports.csv @@ -190,7 +190,7 @@ public;class;ElementGroupsMembers public;interface;ElementGroupsMembersProps public;class;ElementMultiAspect preview;class;ElementMultiAspect -beta;class;ElementOwnsChannelRootAspect +public;class;ElementOwnsChannelRootAspect public;class;ElementOwnsChildElements public;class;ElementOwnsExternalSourceAspects public;class;ElementOwnsMultiAspects